Enable @typescript-eslint/explicit-function-return-type
in /src (#9788)
* Enable `@typescript-eslint/explicit-member-accessibility` on /src * Prettier * Enable `@typescript-eslint/explicit-function-return-type` in /src * Fix types * tsc strict fixes * Delint * Fix test * Fix bad merge
This commit is contained in:
parent
7a36ba0fde
commit
030b7e90bf
683 changed files with 3459 additions and 3013 deletions
|
@ -26,7 +26,7 @@ import { clamp } from "lodash";
|
|||
* @param {number} amt the interpolant
|
||||
* @returns
|
||||
*/
|
||||
export function lerp(start: number, end: number, amt: number) {
|
||||
export function lerp(start: number, end: number, amt: number): number {
|
||||
amt = clamp(amt, 0, 1);
|
||||
return (1 - amt) * start + amt * end;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ export default class DMRoomMap {
|
|||
* Used by tests
|
||||
* @param inst the new shared instance
|
||||
*/
|
||||
public static setShared(inst: DMRoomMap) {
|
||||
public static setShared(inst: DMRoomMap): void {
|
||||
DMRoomMap.sharedInstance = inst;
|
||||
}
|
||||
|
||||
|
@ -75,16 +75,16 @@ export default class DMRoomMap {
|
|||
return DMRoomMap.sharedInstance;
|
||||
}
|
||||
|
||||
public start() {
|
||||
public start(): void {
|
||||
this.populateRoomToUser();
|
||||
this.matrixClient.on(ClientEvent.AccountData, this.onAccountData);
|
||||
}
|
||||
|
||||
public stop() {
|
||||
public stop(): void {
|
||||
this.matrixClient.removeListener(ClientEvent.AccountData, this.onAccountData);
|
||||
}
|
||||
|
||||
private onAccountData = (ev: MatrixEvent) => {
|
||||
private onAccountData = (ev: MatrixEvent): void => {
|
||||
if (ev.getType() == EventType.Direct) {
|
||||
this.mDirectEvent = { ...ev.getContent() }; // copy as we will mutate
|
||||
this.userToRooms = null;
|
||||
|
@ -97,7 +97,7 @@ export default class DMRoomMap {
|
|||
* with ourself, not the other user. Fix it by guessing the other user and
|
||||
* modifying userToRooms
|
||||
*/
|
||||
private patchUpSelfDMs(userToRooms: Record<string, string[]>) {
|
||||
private patchUpSelfDMs(userToRooms: Record<string, string[]>): boolean {
|
||||
const myUserId = this.matrixClient.getUserId();
|
||||
const selfRoomIds = userToRooms[myUserId];
|
||||
if (selfRoomIds) {
|
||||
|
@ -215,7 +215,7 @@ export default class DMRoomMap {
|
|||
return this.userToRooms;
|
||||
}
|
||||
|
||||
private populateRoomToUser() {
|
||||
private populateRoomToUser(): void {
|
||||
this.roomToUser = {};
|
||||
for (const user of Object.keys(this.getUserToRooms())) {
|
||||
for (const roomId of this.userToRooms[user]) {
|
||||
|
|
|
@ -47,13 +47,13 @@ export class DialogOpener {
|
|||
|
||||
// We could do this in the constructor, but then we wouldn't have
|
||||
// a function to call from Lifecycle to capture the class.
|
||||
public prepare() {
|
||||
public prepare(): void {
|
||||
if (this.isRegistered) return;
|
||||
defaultDispatcher.register(this.onDispatch);
|
||||
this.isRegistered = true;
|
||||
}
|
||||
|
||||
private onDispatch = (payload: ActionPayload) => {
|
||||
private onDispatch = (payload: ActionPayload): void => {
|
||||
switch (payload.action) {
|
||||
case "open_room_settings":
|
||||
Modal.createDialog(
|
||||
|
|
|
@ -30,7 +30,7 @@ export default class EditorStateTransfer {
|
|||
|
||||
public constructor(private readonly event: MatrixEvent) {}
|
||||
|
||||
public setEditorState(caret: DocumentOffset, serializedParts: SerializedPart[]) {
|
||||
public setEditorState(caret: DocumentOffset, serializedParts: SerializedPart[]): void {
|
||||
this.caret = caret;
|
||||
this.serializedParts = serializedParts;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ export function messageForResourceLimitError(
|
|||
let errString = strings[limitType];
|
||||
if (errString === undefined) errString = strings[""];
|
||||
|
||||
const linkSub = (sub) => {
|
||||
const linkSub = (sub: string): ReactNode => {
|
||||
if (adminContact) {
|
||||
return (
|
||||
<a href={adminContact} target="_blank" rel="noreferrer noopener">
|
||||
|
|
|
@ -88,7 +88,7 @@ export class FileDownloader {
|
|||
return iframe;
|
||||
}
|
||||
|
||||
public async download({ blob, name, autoDownload = true, opts = DEFAULT_STYLES }: DownloadOptions) {
|
||||
public async download({ blob, name, autoDownload = true, opts = DEFAULT_STYLES }: DownloadOptions): Promise<void> {
|
||||
const iframe = this.iframe; // get the iframe first just in case we need to await onload
|
||||
if (this.onLoadPromise) await this.onLoadPromise;
|
||||
iframe.contentWindow.postMessage(
|
||||
|
|
|
@ -43,7 +43,7 @@ export class FixedRollingArray<T> {
|
|||
* Pushes a value to the array.
|
||||
* @param value The value to push.
|
||||
*/
|
||||
public pushValue(value: T) {
|
||||
public pushValue(value: T): void {
|
||||
let swap = arrayFastClone(this.samples);
|
||||
swap.splice(0, 0, value);
|
||||
if (swap.length > this.width) {
|
||||
|
|
|
@ -35,14 +35,14 @@ export class MarkedExecution {
|
|||
/**
|
||||
* Resets the mark without calling the function.
|
||||
*/
|
||||
public reset() {
|
||||
public reset(): void {
|
||||
this.marked = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the function to be called upon trigger().
|
||||
*/
|
||||
public mark() {
|
||||
public mark(): void {
|
||||
if (!this.marked) this.onMarkCallback?.();
|
||||
this.marked = true;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ export class MarkedExecution {
|
|||
/**
|
||||
* If marked, the function will be called, otherwise this does nothing.
|
||||
*/
|
||||
public trigger() {
|
||||
public trigger(): void {
|
||||
if (!this.marked) return;
|
||||
this.reset(); // reset first just in case the fn() causes a trigger()
|
||||
this.fn();
|
||||
|
|
|
@ -54,14 +54,14 @@ export class MediaEventHelper implements IDestroyable {
|
|||
);
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
public destroy(): void {
|
||||
if (this.media.isEncrypted) {
|
||||
if (this.sourceUrl.present) URL.revokeObjectURL(this.sourceUrl.cachedValue);
|
||||
if (this.thumbnailUrl.present) URL.revokeObjectURL(this.thumbnailUrl.cachedValue);
|
||||
}
|
||||
}
|
||||
|
||||
private prepareSourceUrl = async () => {
|
||||
private prepareSourceUrl = async (): Promise<string> => {
|
||||
if (this.media.isEncrypted) {
|
||||
const blob = await this.sourceBlob.value;
|
||||
return URL.createObjectURL(blob);
|
||||
|
@ -70,7 +70,7 @@ export class MediaEventHelper implements IDestroyable {
|
|||
}
|
||||
};
|
||||
|
||||
private prepareThumbnailUrl = async () => {
|
||||
private prepareThumbnailUrl = async (): Promise<string> => {
|
||||
if (this.media.isEncrypted) {
|
||||
const blob = await this.thumbnailBlob.value;
|
||||
if (blob === null) return null;
|
||||
|
@ -80,7 +80,7 @@ export class MediaEventHelper implements IDestroyable {
|
|||
}
|
||||
};
|
||||
|
||||
private fetchSource = () => {
|
||||
private fetchSource = (): Promise<Blob> => {
|
||||
if (this.media.isEncrypted) {
|
||||
const content = this.event.getContent<IMediaEventContent>();
|
||||
return decryptFile(content.file, content.info);
|
||||
|
@ -88,7 +88,7 @@ export class MediaEventHelper implements IDestroyable {
|
|||
return this.media.downloadSource().then((r) => r.blob());
|
||||
};
|
||||
|
||||
private fetchThumbnail = () => {
|
||||
private fetchThumbnail = (): Promise<Blob> => {
|
||||
if (!this.media.hasThumbnail) return Promise.resolve(null);
|
||||
|
||||
if (this.media.isEncrypted) {
|
||||
|
|
|
@ -74,9 +74,16 @@ function wrapDeletion(child: Node): HTMLElement {
|
|||
return wrapper;
|
||||
}
|
||||
|
||||
function findRefNodes(root: Node, route: number[], isAddition = false) {
|
||||
function findRefNodes(
|
||||
root: Node,
|
||||
route: number[],
|
||||
isAddition = false,
|
||||
): {
|
||||
refNode: Node;
|
||||
refParentNode?: Node;
|
||||
} {
|
||||
let refNode = root;
|
||||
let refParentNode;
|
||||
let refParentNode: Node | undefined;
|
||||
const end = isAddition ? route.length - 1 : route.length;
|
||||
for (let i = 0; i < end; ++i) {
|
||||
refParentNode = refNode;
|
||||
|
@ -85,8 +92,12 @@ function findRefNodes(root: Node, route: number[], isAddition = false) {
|
|||
return { refNode, refParentNode };
|
||||
}
|
||||
|
||||
function diffTreeToDOM(desc) {
|
||||
if (desc.nodeName === "#text") {
|
||||
function isTextNode(node: Text | HTMLElement): node is Text {
|
||||
return node.nodeName === "#text";
|
||||
}
|
||||
|
||||
function diffTreeToDOM(desc): Node {
|
||||
if (isTextNode(desc)) {
|
||||
return stringAsTextNode(desc.data);
|
||||
} else {
|
||||
const node = document.createElement(desc.nodeName);
|
||||
|
@ -97,7 +108,7 @@ function diffTreeToDOM(desc) {
|
|||
}
|
||||
if (desc.childNodes) {
|
||||
for (const childDesc of desc.childNodes) {
|
||||
node.appendChild(diffTreeToDOM(childDesc));
|
||||
node.appendChild(diffTreeToDOM(childDesc as Text | HTMLElement));
|
||||
}
|
||||
}
|
||||
return node;
|
||||
|
@ -152,25 +163,25 @@ function renderDifferenceInDOM(originalRootNode: Node, diff: IDiff, diffMathPatc
|
|||
switch (diff.action) {
|
||||
case "replaceElement": {
|
||||
const container = document.createElement("span");
|
||||
const delNode = wrapDeletion(diffTreeToDOM(diff.oldValue));
|
||||
const insNode = wrapInsertion(diffTreeToDOM(diff.newValue));
|
||||
const delNode = wrapDeletion(diffTreeToDOM(diff.oldValue as HTMLElement));
|
||||
const insNode = wrapInsertion(diffTreeToDOM(diff.newValue as HTMLElement));
|
||||
container.appendChild(delNode);
|
||||
container.appendChild(insNode);
|
||||
refNode.parentNode.replaceChild(container, refNode);
|
||||
break;
|
||||
}
|
||||
case "removeTextElement": {
|
||||
const delNode = wrapDeletion(stringAsTextNode(diff.value));
|
||||
const delNode = wrapDeletion(stringAsTextNode(diff.value as string));
|
||||
refNode.parentNode.replaceChild(delNode, refNode);
|
||||
break;
|
||||
}
|
||||
case "removeElement": {
|
||||
const delNode = wrapDeletion(diffTreeToDOM(diff.element));
|
||||
const delNode = wrapDeletion(diffTreeToDOM(diff.element as HTMLElement));
|
||||
refNode.parentNode.replaceChild(delNode, refNode);
|
||||
break;
|
||||
}
|
||||
case "modifyTextElement": {
|
||||
const textDiffs = diffMathPatch.diff_main(diff.oldValue, diff.newValue);
|
||||
const textDiffs = diffMathPatch.diff_main(diff.oldValue as string, diff.newValue as string);
|
||||
diffMathPatch.diff_cleanupSemantic(textDiffs);
|
||||
const container = document.createElement("span");
|
||||
for (const [modifier, text] of textDiffs) {
|
||||
|
@ -186,7 +197,7 @@ function renderDifferenceInDOM(originalRootNode: Node, diff: IDiff, diffMathPatc
|
|||
break;
|
||||
}
|
||||
case "addElement": {
|
||||
const insNode = wrapInsertion(diffTreeToDOM(diff.element));
|
||||
const insNode = wrapInsertion(diffTreeToDOM(diff.element as HTMLElement));
|
||||
insertBefore(refParentNode, refNode, insNode);
|
||||
break;
|
||||
}
|
||||
|
@ -194,7 +205,7 @@ function renderDifferenceInDOM(originalRootNode: Node, diff: IDiff, diffMathPatc
|
|||
// XXX: sometimes diffDOM says insert a newline when there shouldn't be one
|
||||
// but we must insert the node anyway so that we don't break the route child IDs.
|
||||
// See https://github.com/fiduswriter/diffDOM/issues/100
|
||||
const insNode = wrapInsertion(stringAsTextNode(diff.value !== "\n" ? diff.value : ""));
|
||||
const insNode = wrapInsertion(stringAsTextNode(diff.value !== "\n" ? (diff.value as string) : ""));
|
||||
insertBefore(refParentNode, refNode, insNode);
|
||||
break;
|
||||
}
|
||||
|
@ -206,7 +217,7 @@ function renderDifferenceInDOM(originalRootNode: Node, diff: IDiff, diffMathPatc
|
|||
const delNode = wrapDeletion(refNode.cloneNode(true));
|
||||
const updatedNode = refNode.cloneNode(true) as HTMLElement;
|
||||
if (diff.action === "addAttribute" || diff.action === "modifyAttribute") {
|
||||
updatedNode.setAttribute(diff.name, diff.newValue);
|
||||
updatedNode.setAttribute(diff.name, diff.newValue as string);
|
||||
} else {
|
||||
updatedNode.removeAttribute(diff.name);
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ export default class MultiInviter {
|
|||
this.matrixClient = MatrixClientPeg.get();
|
||||
}
|
||||
|
||||
public get fatal() {
|
||||
public get fatal(): boolean {
|
||||
return this._fatal;
|
||||
}
|
||||
|
||||
|
@ -112,8 +112,8 @@ export default class MultiInviter {
|
|||
return this.deferred.promise;
|
||||
}
|
||||
|
||||
return this.deferred.promise.then(async (states) => {
|
||||
const invitedUsers = [];
|
||||
return this.deferred.promise.then(async (states): Promise<CompletionStates> => {
|
||||
const invitedUsers: string[] = [];
|
||||
for (const [addr, state] of Object.entries(states)) {
|
||||
if (state === InviteState.Invited && getAddressType(addr) === AddressType.MatrixUserId) {
|
||||
invitedUsers.push(addr);
|
||||
|
@ -308,7 +308,7 @@ export default class MultiInviter {
|
|||
);
|
||||
|
||||
if (unknownProfileUsers.length > 0) {
|
||||
const inviteUnknowns = () => {
|
||||
const inviteUnknowns = (): void => {
|
||||
const promises = unknownProfileUsers.map((u) => this.doInvite(u, true));
|
||||
Promise.all(promises).then(() => this.deferred.resolve(this.completionStates));
|
||||
};
|
||||
|
|
|
@ -60,7 +60,7 @@ _td("Short keyboard patterns are easy to guess");
|
|||
* @param {string} password Password to score
|
||||
* @returns {object} Score result with `score` and `feedback` properties
|
||||
*/
|
||||
export function scorePassword(password: string) {
|
||||
export function scorePassword(password: string): zxcvbn.ZXCVBNResult {
|
||||
if (password.length === 0) return null;
|
||||
|
||||
const userInputs = ZXCVBN_USER_INPUTS.slice();
|
||||
|
|
|
@ -33,46 +33,46 @@ export default class ResizeNotifier extends EventEmitter {
|
|||
// if there was another call in that timespan
|
||||
private throttledMiddlePanel = throttle(() => this.emit("middlePanelResized"), 200);
|
||||
|
||||
public get isResizing() {
|
||||
public get isResizing(): boolean {
|
||||
return this._isResizing;
|
||||
}
|
||||
|
||||
public startResizing() {
|
||||
public startResizing(): void {
|
||||
this._isResizing = true;
|
||||
this.emit("isResizing", true);
|
||||
}
|
||||
|
||||
public stopResizing() {
|
||||
public stopResizing(): void {
|
||||
this._isResizing = false;
|
||||
this.emit("isResizing", false);
|
||||
}
|
||||
|
||||
private noisyMiddlePanel() {
|
||||
private noisyMiddlePanel(): void {
|
||||
this.emit("middlePanelResizedNoisy");
|
||||
}
|
||||
|
||||
private updateMiddlePanel() {
|
||||
private updateMiddlePanel(): void {
|
||||
this.throttledMiddlePanel();
|
||||
this.noisyMiddlePanel();
|
||||
}
|
||||
|
||||
// can be called in quick succession
|
||||
public notifyLeftHandleResized() {
|
||||
public notifyLeftHandleResized(): void {
|
||||
// don't emit event for own region
|
||||
this.updateMiddlePanel();
|
||||
}
|
||||
|
||||
// can be called in quick succession
|
||||
public notifyRightHandleResized() {
|
||||
public notifyRightHandleResized(): void {
|
||||
this.updateMiddlePanel();
|
||||
}
|
||||
|
||||
public notifyTimelineHeightChanged() {
|
||||
public notifyTimelineHeightChanged(): void {
|
||||
this.updateMiddlePanel();
|
||||
}
|
||||
|
||||
// can be called in quick succession
|
||||
public notifyWindowResized() {
|
||||
public notifyWindowResized(): void {
|
||||
this.updateMiddlePanel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ export async function awaitRoomDownSync(cli: MatrixClient, roomId: string): Prom
|
|||
// We have to wait for the js-sdk to give us the room back so
|
||||
// we can more effectively abuse the MultiInviter behaviour
|
||||
// which heavily relies on the Room object being available.
|
||||
const checkForRoomFn = (room: Room) => {
|
||||
const checkForRoomFn = (room: Room): void => {
|
||||
if (room.roomId !== roomId) return;
|
||||
resolve(room);
|
||||
cli.off(ClientEvent.Room, checkForRoomFn);
|
||||
|
|
|
@ -64,14 +64,14 @@ export class Singleflight {
|
|||
* Forgets all results for a given instance.
|
||||
* @param {Object} instance The instance to forget about.
|
||||
*/
|
||||
public static forgetAllFor(instance: Object) {
|
||||
public static forgetAllFor(instance: Object): void {
|
||||
keyMap.delete(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forgets all cached results for all instances. Intended for use by tests.
|
||||
*/
|
||||
public static forgetAll() {
|
||||
public static forgetAll(): void {
|
||||
for (const k of keyMap.keys()) {
|
||||
keyMap.remove(k);
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ class SingleflightContext {
|
|||
/**
|
||||
* Forget this particular instance and key combination, discarding the result.
|
||||
*/
|
||||
public forget() {
|
||||
public forget(): void {
|
||||
const map = keyMap.get(this.instance);
|
||||
if (!map) return;
|
||||
map.remove(this.key);
|
||||
|
|
|
@ -29,7 +29,7 @@ export class SnakedObject<T = Record<string, any>> {
|
|||
}
|
||||
|
||||
// Make JSON.stringify() pretend that everything is fine
|
||||
public toJSON() {
|
||||
public toJSON(): T {
|
||||
return this.obj;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,15 +32,15 @@ try {
|
|||
const SYNC_STORE_NAME = "riot-web-sync";
|
||||
const CRYPTO_STORE_NAME = "matrix-js-sdk:crypto";
|
||||
|
||||
function log(msg: string) {
|
||||
function log(msg: string): void {
|
||||
logger.log(`StorageManager: ${msg}`);
|
||||
}
|
||||
|
||||
function error(msg: string, ...args: string[]) {
|
||||
function error(msg: string, ...args: string[]): void {
|
||||
logger.error(`StorageManager: ${msg}`, ...args);
|
||||
}
|
||||
|
||||
export function tryPersistStorage() {
|
||||
export function tryPersistStorage(): void {
|
||||
if (navigator.storage && navigator.storage.persist) {
|
||||
navigator.storage.persist().then((persistent) => {
|
||||
logger.log("StorageManager: Persistent?", persistent);
|
||||
|
@ -56,7 +56,12 @@ export function tryPersistStorage() {
|
|||
}
|
||||
}
|
||||
|
||||
export async function checkConsistency() {
|
||||
export async function checkConsistency(): Promise<{
|
||||
healthy: boolean;
|
||||
cryptoInited: boolean;
|
||||
dataInCryptoStore: boolean;
|
||||
dataInLocalStorage: boolean;
|
||||
}> {
|
||||
log("Checking storage consistency");
|
||||
log(`Local storage supported? ${!!localStorage}`);
|
||||
log(`IndexedDB supported? ${!!indexedDB}`);
|
||||
|
@ -121,7 +126,12 @@ export async function checkConsistency() {
|
|||
};
|
||||
}
|
||||
|
||||
async function checkSyncStore() {
|
||||
interface StoreCheck {
|
||||
exists: boolean;
|
||||
healthy: boolean;
|
||||
}
|
||||
|
||||
async function checkSyncStore(): Promise<StoreCheck> {
|
||||
let exists = false;
|
||||
try {
|
||||
exists = await IndexedDBStore.exists(indexedDB, SYNC_STORE_NAME);
|
||||
|
@ -134,7 +144,7 @@ async function checkSyncStore() {
|
|||
return { exists, healthy: false };
|
||||
}
|
||||
|
||||
async function checkCryptoStore() {
|
||||
async function checkCryptoStore(): Promise<StoreCheck> {
|
||||
let exists = false;
|
||||
try {
|
||||
exists = await IndexedDBCryptoStore.exists(indexedDB, CRYPTO_STORE_NAME);
|
||||
|
@ -164,7 +174,7 @@ async function checkCryptoStore() {
|
|||
*
|
||||
* @param {boolean} cryptoInited True if crypto has been set up
|
||||
*/
|
||||
export function setCryptoInitialised(cryptoInited: boolean) {
|
||||
export function setCryptoInitialised(cryptoInited: boolean): void {
|
||||
localStorage.setItem("mx_crypto_initialised", String(cryptoInited));
|
||||
}
|
||||
|
||||
|
@ -180,10 +190,10 @@ async function idbInit(): Promise<void> {
|
|||
idb = await new Promise((resolve, reject) => {
|
||||
const request = indexedDB.open("matrix-react-sdk", 1);
|
||||
request.onerror = reject;
|
||||
request.onsuccess = () => {
|
||||
request.onsuccess = (): void => {
|
||||
resolve(request.result);
|
||||
};
|
||||
request.onupgradeneeded = () => {
|
||||
request.onupgradeneeded = (): void => {
|
||||
const db = request.result;
|
||||
db.createObjectStore("pickleKey");
|
||||
db.createObjectStore("account");
|
||||
|
@ -202,7 +212,7 @@ export async function idbLoad(table: string, key: string | string[]): Promise<an
|
|||
const objectStore = txn.objectStore(table);
|
||||
const request = objectStore.get(key);
|
||||
request.onerror = reject;
|
||||
request.onsuccess = (event) => {
|
||||
request.onsuccess = (event): void => {
|
||||
resolve(request.result);
|
||||
};
|
||||
});
|
||||
|
@ -219,7 +229,7 @@ export async function idbSave(table: string, key: string | string[], data: any):
|
|||
const objectStore = txn.objectStore(table);
|
||||
const request = objectStore.put(data, key);
|
||||
request.onerror = reject;
|
||||
request.onsuccess = (event) => {
|
||||
request.onsuccess = (event): void => {
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
|
@ -236,7 +246,7 @@ export async function idbDelete(table: string, key: string | string[]): Promise<
|
|||
const objectStore = txn.objectStore(table);
|
||||
const request = objectStore.delete(key);
|
||||
request.onerror = reject;
|
||||
request.onsuccess = () => {
|
||||
request.onsuccess = (): void => {
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
|
|
|
@ -36,7 +36,7 @@ export default class Timer {
|
|||
this.setNotStarted();
|
||||
}
|
||||
|
||||
private setNotStarted() {
|
||||
private setNotStarted(): void {
|
||||
this.timerHandle = null;
|
||||
this.startTs = null;
|
||||
this.promise = new Promise<void>((resolve, reject) => {
|
||||
|
@ -47,7 +47,7 @@ export default class Timer {
|
|||
});
|
||||
}
|
||||
|
||||
private onTimeout = () => {
|
||||
private onTimeout = (): void => {
|
||||
const now = Date.now();
|
||||
const elapsed = now - this.startTs;
|
||||
if (elapsed >= this.timeout) {
|
||||
|
@ -59,7 +59,7 @@ export default class Timer {
|
|||
}
|
||||
};
|
||||
|
||||
public changeTimeout(timeout: number) {
|
||||
public changeTimeout(timeout: number): void {
|
||||
if (timeout === this.timeout) {
|
||||
return;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ export default class Timer {
|
|||
* if not started before, starts the timer.
|
||||
* @returns {Timer} the same timer
|
||||
*/
|
||||
public start() {
|
||||
public start(): Timer {
|
||||
if (!this.isRunning()) {
|
||||
this.startTs = Date.now();
|
||||
this.timerHandle = window.setTimeout(this.onTimeout, this.timeout);
|
||||
|
@ -87,7 +87,7 @@ export default class Timer {
|
|||
* (re)start the timer. If it's running, reset the timeout. If not, start it.
|
||||
* @returns {Timer} the same timer
|
||||
*/
|
||||
public restart() {
|
||||
public restart(): Timer {
|
||||
if (this.isRunning()) {
|
||||
// don't clearTimeout here as this method
|
||||
// can be called in fast succession,
|
||||
|
@ -105,7 +105,7 @@ export default class Timer {
|
|||
* and reject the promise for this timer.
|
||||
* @returns {Timer} the same timer
|
||||
*/
|
||||
public abort() {
|
||||
public abort(): Timer {
|
||||
if (this.isRunning()) {
|
||||
clearTimeout(this.timerHandle);
|
||||
this.reject(new Error("Timer was aborted."));
|
||||
|
@ -119,11 +119,11 @@ export default class Timer {
|
|||
*or is rejected when abort is called
|
||||
*@return {Promise}
|
||||
*/
|
||||
public finished() {
|
||||
public finished(): Promise<void> {
|
||||
return this.promise;
|
||||
}
|
||||
|
||||
public isRunning() {
|
||||
public isRunning(): boolean {
|
||||
return this.timerHandle !== null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ limitations under the License.
|
|||
* @param {*} opts The options (properties) to set on the object.
|
||||
* @returns {*} The created object.
|
||||
*/
|
||||
export function makeType(Type: any, opts: any) {
|
||||
export function makeType<T>(Type: { new (): T }, opts: Partial<T>): T {
|
||||
const c = new Type();
|
||||
Object.assign(c, opts);
|
||||
return c;
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
export class ValidatedServerConfig {
|
||||
public hsUrl: string;
|
||||
public hsName: string;
|
||||
public hsNameIsDifferent: string;
|
||||
public hsNameIsDifferent: boolean;
|
||||
|
||||
public isUrl: string;
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ export abstract class Whenable<T> implements IDestroyable {
|
|||
* Notifies all the listeners of a given condition.
|
||||
* @param condition The new condition that has been met.
|
||||
*/
|
||||
protected notifyCondition(condition: T) {
|
||||
protected notifyCondition(condition: T): void {
|
||||
const listeners = arrayFastClone(this.listeners); // clone just in case the handler modifies us
|
||||
for (const listener of listeners) {
|
||||
if (listener.condition === null || listener.condition === condition) {
|
||||
|
@ -81,7 +81,7 @@ export abstract class Whenable<T> implements IDestroyable {
|
|||
}
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
public destroy(): void {
|
||||
this.listeners = [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ export default class WidgetUtils {
|
|||
return new Promise((resolve, reject) => {
|
||||
// Tests an account data event, returning true if it's in the state
|
||||
// we're waiting for it to be in
|
||||
function eventInIntendedState(ev) {
|
||||
function eventInIntendedState(ev): boolean {
|
||||
if (!ev || !ev.getContent()) return false;
|
||||
if (add) {
|
||||
return ev.getContent()[widgetId] !== undefined;
|
||||
|
@ -158,7 +158,7 @@ export default class WidgetUtils {
|
|||
return;
|
||||
}
|
||||
|
||||
function onAccountData(ev) {
|
||||
function onAccountData(ev): void {
|
||||
const currentAccountDataEvent = MatrixClientPeg.get().getAccountData("m.widgets");
|
||||
if (eventInIntendedState(currentAccountDataEvent)) {
|
||||
MatrixClientPeg.get().removeListener(ClientEvent.AccountData, onAccountData);
|
||||
|
@ -190,7 +190,7 @@ export default class WidgetUtils {
|
|||
return new Promise((resolve, reject) => {
|
||||
// Tests a list of state events, returning true if it's in the state
|
||||
// we're waiting for it to be in
|
||||
function eventsInIntendedState(evList) {
|
||||
function eventsInIntendedState(evList: MatrixEvent[]): boolean {
|
||||
const widgetPresent = evList.some((ev) => {
|
||||
return ev.getContent() && ev.getContent()["id"] === widgetId;
|
||||
});
|
||||
|
@ -209,7 +209,7 @@ export default class WidgetUtils {
|
|||
return;
|
||||
}
|
||||
|
||||
function onRoomStateEvents(ev: MatrixEvent) {
|
||||
function onRoomStateEvents(ev: MatrixEvent): void {
|
||||
if (ev.getRoomId() !== roomId || ev.getType() !== "im.vector.modular.widgets") return;
|
||||
|
||||
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
|
||||
|
@ -235,7 +235,7 @@ export default class WidgetUtils {
|
|||
widgetUrl: string,
|
||||
widgetName: string,
|
||||
widgetData: IWidgetData,
|
||||
) {
|
||||
): Promise<void> {
|
||||
const content = {
|
||||
type: widgetType.preferred,
|
||||
url: widgetUrl,
|
||||
|
@ -288,10 +288,10 @@ export default class WidgetUtils {
|
|||
widgetType?: WidgetType,
|
||||
widgetUrl?: string,
|
||||
widgetName?: string,
|
||||
widgetData?: object,
|
||||
widgetData?: IWidgetData,
|
||||
widgetAvatarUrl?: string,
|
||||
) {
|
||||
let content;
|
||||
): Promise<void> {
|
||||
let content: Partial<IWidget> & { avatar_url?: string };
|
||||
|
||||
const addingWidget = Boolean(widgetUrl);
|
||||
|
||||
|
@ -309,10 +309,10 @@ export default class WidgetUtils {
|
|||
content = {};
|
||||
}
|
||||
|
||||
return WidgetUtils.setRoomWidgetContent(roomId, widgetId, content);
|
||||
return WidgetUtils.setRoomWidgetContent(roomId, widgetId, content as IWidget);
|
||||
}
|
||||
|
||||
public static setRoomWidgetContent(roomId: string, widgetId: string, content: IWidget) {
|
||||
public static setRoomWidgetContent(roomId: string, widgetId: string, content: IWidget): Promise<void> {
|
||||
const addingWidget = !!content.url;
|
||||
|
||||
WidgetEchoStore.setRoomWidgetEcho(roomId, widgetId, content);
|
||||
|
@ -334,7 +334,7 @@ export default class WidgetUtils {
|
|||
* @param {Room} room The room to get widgets force
|
||||
* @return {[object]} Array containing current / active room widgets
|
||||
*/
|
||||
public static getRoomWidgets(room: Room) {
|
||||
public static getRoomWidgets(room: Room): MatrixEvent[] {
|
||||
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
|
||||
const appsStateEvents = room.currentState.getStateEvents("im.vector.modular.widgets");
|
||||
if (!appsStateEvents) {
|
||||
|
@ -500,7 +500,7 @@ export default class WidgetUtils {
|
|||
return app as IApp;
|
||||
}
|
||||
|
||||
public static getLocalJitsiWrapperUrl(opts: { forLocalRender?: boolean; auth?: string } = {}) {
|
||||
public static getLocalJitsiWrapperUrl(opts: { forLocalRender?: boolean; auth?: string } = {}): string {
|
||||
// NB. we can't just encodeURIComponent all of these because the $ signs need to be there
|
||||
const queryStringParts = [
|
||||
"conferenceDomain=$domain",
|
||||
|
@ -557,7 +557,7 @@ export default class WidgetUtils {
|
|||
.open(room, "type_" + app.type, app.id);
|
||||
}
|
||||
|
||||
public static isManagedByManager(app) {
|
||||
public static isManagedByManager(app: IApp): boolean {
|
||||
if (WidgetUtils.isScalarUrl(app.url)) {
|
||||
const managers = IntegrationManagers.sharedInstance();
|
||||
if (managers.hasManager()) {
|
||||
|
|
|
@ -132,9 +132,9 @@ export const watchPosition = (
|
|||
onWatchPositionError: (error: GeolocationError) => void,
|
||||
): ClearWatchCallback => {
|
||||
try {
|
||||
const onError = (error) => onWatchPositionError(mapGeolocationError(error));
|
||||
const onError = (error): void => onWatchPositionError(mapGeolocationError(error));
|
||||
const watchId = getGeolocation().watchPosition(onWatchPosition, onError, GeolocationOptions);
|
||||
const clearWatch = () => {
|
||||
const clearWatch = (): void => {
|
||||
getGeolocation().clearWatch(watchId);
|
||||
};
|
||||
return clearWatch;
|
||||
|
|
|
@ -69,7 +69,7 @@ export const useOwnLiveBeacons = (liveBeaconIds: BeaconIdentifier[]): LiveBeacon
|
|||
.sort(sortBeaconsByLatestExpiry)
|
||||
.shift();
|
||||
|
||||
const onStopSharing = async () => {
|
||||
const onStopSharing = async (): Promise<void> => {
|
||||
setStoppingInProgress(true);
|
||||
try {
|
||||
await Promise.all(liveBeaconIds.map((beaconId) => OwnBeaconStore.instance.stopBeacon(beaconId)));
|
||||
|
@ -78,7 +78,7 @@ export const useOwnLiveBeacons = (liveBeaconIds: BeaconIdentifier[]): LiveBeacon
|
|||
}
|
||||
};
|
||||
|
||||
const onResetLocationPublishError = () => {
|
||||
const onResetLocationPublishError = (): void => {
|
||||
liveBeaconIds.forEach((beaconId) => {
|
||||
OwnBeaconStore.instance.resetLocationPublishError(beaconId);
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { IEncryptedFile, MsgType } from "matrix-js-sdk/src/matrix";
|
||||
import { IContent, IEncryptedFile, MsgType } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
/**
|
||||
* @param {string} mxc MXC URL of the file
|
||||
|
@ -31,7 +31,7 @@ export const createVoiceMessageContent = (
|
|||
size: number,
|
||||
file?: IEncryptedFile,
|
||||
waveform?: number[],
|
||||
) => {
|
||||
): IContent => {
|
||||
return {
|
||||
"body": "Voice message",
|
||||
//"msgtype": "org.matrix.msc2516.voice",
|
||||
|
|
|
@ -19,7 +19,7 @@ import { logger } from "matrix-js-sdk/src/logger";
|
|||
const SNOOZE_KEY = "mx_snooze_bulk_unverified_device_nag";
|
||||
// one week
|
||||
const snoozePeriod = 1000 * 60 * 60 * 24 * 7;
|
||||
export const snoozeBulkUnverifiedDeviceReminder = () => {
|
||||
export const snoozeBulkUnverifiedDeviceReminder = (): void => {
|
||||
try {
|
||||
localStorage.setItem(SNOOZE_KEY, String(Date.now()));
|
||||
} catch (error) {
|
||||
|
@ -27,7 +27,7 @@ export const snoozeBulkUnverifiedDeviceReminder = () => {
|
|||
}
|
||||
};
|
||||
|
||||
export const isBulkUnverifiedDeviceReminderSnoozed = () => {
|
||||
export const isBulkUnverifiedDeviceReminderSnoozed = (): boolean => {
|
||||
try {
|
||||
const snoozedTimestamp = localStorage.getItem(SNOOZE_KEY);
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ export default abstract class Exporter {
|
|||
this.cancelled = true;
|
||||
}
|
||||
|
||||
protected downloadPlainText(fileName: string, text: string) {
|
||||
protected downloadPlainText(fileName: string, text: string): void {
|
||||
const content = new Blob([text], { type: "text/plain" });
|
||||
saveAs(content, fileName);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React, { ReactNode } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
|
@ -65,7 +65,7 @@ export default class HTMLExporter extends Exporter {
|
|||
this.threadsEnabled = SettingsStore.getValue("feature_threadenabled");
|
||||
}
|
||||
|
||||
protected async getRoomAvatar() {
|
||||
protected async getRoomAvatar(): Promise<ReactNode> {
|
||||
let blob: Blob;
|
||||
const avatarUrl = Avatar.avatarUrlForRoom(this.room, 32, 32, "crop");
|
||||
const avatarPath = "room.png";
|
||||
|
@ -92,7 +92,7 @@ export default class HTMLExporter extends Exporter {
|
|||
return renderToStaticMarkup(avatar);
|
||||
}
|
||||
|
||||
protected async wrapHTML(content: string) {
|
||||
protected async wrapHTML(content: string): Promise<string> {
|
||||
const roomAvatar = await this.getRoomAvatar();
|
||||
const exportDate = formatFullDateNoDayNoTime(new Date());
|
||||
const creator = this.room.currentState.getStateEvents(EventType.RoomCreate, "")?.getSender();
|
||||
|
@ -224,7 +224,7 @@ export default class HTMLExporter extends Exporter {
|
|||
);
|
||||
}
|
||||
|
||||
protected async saveAvatarIfNeeded(event: MatrixEvent) {
|
||||
protected async saveAvatarIfNeeded(event: MatrixEvent): Promise<void> {
|
||||
const member = event.sender;
|
||||
if (!this.avatars.has(member.userId)) {
|
||||
try {
|
||||
|
@ -239,7 +239,7 @@ export default class HTMLExporter extends Exporter {
|
|||
}
|
||||
}
|
||||
|
||||
protected getDateSeparator(event: MatrixEvent) {
|
||||
protected async getDateSeparator(event: MatrixEvent): Promise<string> {
|
||||
const ts = event.getTs();
|
||||
const dateSeparator = (
|
||||
<li key={ts}>
|
||||
|
@ -249,12 +249,12 @@ export default class HTMLExporter extends Exporter {
|
|||
return renderToStaticMarkup(dateSeparator);
|
||||
}
|
||||
|
||||
protected needsDateSeparator(event: MatrixEvent, prevEvent: MatrixEvent) {
|
||||
protected async needsDateSeparator(event: MatrixEvent, prevEvent: MatrixEvent): Promise<boolean> {
|
||||
if (prevEvent == null) return true;
|
||||
return wantsDateSeparator(prevEvent.getDate(), event.getDate());
|
||||
}
|
||||
|
||||
public getEventTile(mxEv: MatrixEvent, continuation: boolean) {
|
||||
public getEventTile(mxEv: MatrixEvent, continuation: boolean): JSX.Element {
|
||||
return (
|
||||
<div className="mx_Export_EventWrapper" id={mxEv.getId()}>
|
||||
<MatrixClientContext.Provider value={this.client}>
|
||||
|
@ -285,7 +285,7 @@ export default class HTMLExporter extends Exporter {
|
|||
);
|
||||
}
|
||||
|
||||
protected async getEventTileMarkup(mxEv: MatrixEvent, continuation: boolean, filePath?: string) {
|
||||
protected async getEventTileMarkup(mxEv: MatrixEvent, continuation: boolean, filePath?: string): Promise<string> {
|
||||
const hasAvatar = !!this.getAvatarURL(mxEv);
|
||||
if (hasAvatar) await this.saveAvatarIfNeeded(mxEv);
|
||||
const EventTile = this.getEventTile(mxEv, continuation);
|
||||
|
@ -319,7 +319,7 @@ export default class HTMLExporter extends Exporter {
|
|||
return eventTileMarkup;
|
||||
}
|
||||
|
||||
protected createModifiedEvent(text: string, mxEv: MatrixEvent, italic = true) {
|
||||
protected createModifiedEvent(text: string, mxEv: MatrixEvent, italic = true): MatrixEvent {
|
||||
const modifiedContent = {
|
||||
msgtype: "m.text",
|
||||
body: `${text}`,
|
||||
|
@ -338,7 +338,7 @@ export default class HTMLExporter extends Exporter {
|
|||
return modifiedEvent;
|
||||
}
|
||||
|
||||
protected async createMessageBody(mxEv: MatrixEvent, joined = false) {
|
||||
protected async createMessageBody(mxEv: MatrixEvent, joined = false): Promise<string> {
|
||||
let eventTile: string;
|
||||
try {
|
||||
if (this.isAttachment(mxEv)) {
|
||||
|
@ -387,7 +387,7 @@ export default class HTMLExporter extends Exporter {
|
|||
return eventTile;
|
||||
}
|
||||
|
||||
protected async createHTML(events: MatrixEvent[], start: number) {
|
||||
protected async createHTML(events: MatrixEvent[], start: number): Promise<string> {
|
||||
let content = "";
|
||||
let prevEvent = null;
|
||||
for (let i = start; i < Math.min(start + 1000, events.length); i++) {
|
||||
|
@ -415,7 +415,7 @@ export default class HTMLExporter extends Exporter {
|
|||
return this.wrapHTML(content);
|
||||
}
|
||||
|
||||
public async export() {
|
||||
public async export(): Promise<void> {
|
||||
this.updateProgress(_t("Starting export..."));
|
||||
|
||||
const fetchStart = performance.now();
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { IEvent, MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
|
@ -60,7 +60,7 @@ export default class JSONExporter extends Exporter {
|
|||
return JSON.stringify(jsonObject, null, 2);
|
||||
}
|
||||
|
||||
protected async getJSONString(mxEv: MatrixEvent) {
|
||||
protected async getJSONString(mxEv: MatrixEvent): Promise<IEvent> {
|
||||
if (this.exportOptions.attachmentsIncluded && this.isAttachment(mxEv)) {
|
||||
try {
|
||||
const blob = await this.getMediaBlob(mxEv);
|
||||
|
@ -81,7 +81,7 @@ export default class JSONExporter extends Exporter {
|
|||
return clearEvent;
|
||||
}
|
||||
|
||||
protected async createOutput(events: MatrixEvent[]) {
|
||||
protected async createOutput(events: MatrixEvent[]): Promise<string> {
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const event = events[i];
|
||||
this.updateProgress(
|
||||
|
@ -99,7 +99,7 @@ export default class JSONExporter extends Exporter {
|
|||
return this.createJSONString();
|
||||
}
|
||||
|
||||
public async export() {
|
||||
public async export(): Promise<void> {
|
||||
logger.info("Starting export process...");
|
||||
logger.info("Fetching events...");
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ export default class PlainTextExporter extends Exporter {
|
|||
return this.makeFileNameNoExtension() + ".txt";
|
||||
}
|
||||
|
||||
public textForReplyEvent = (content: IContent) => {
|
||||
public textForReplyEvent = (content: IContent): string => {
|
||||
const REPLY_REGEX = /> <(.*?)>(.*?)\n\n(.*)/s;
|
||||
const REPLY_SOURCE_MAX_LENGTH = 32;
|
||||
|
||||
|
@ -79,7 +79,7 @@ export default class PlainTextExporter extends Exporter {
|
|||
return `<${rplName}${rplSource}> ${rplText}`;
|
||||
};
|
||||
|
||||
protected plainTextForEvent = async (mxEv: MatrixEvent) => {
|
||||
protected plainTextForEvent = async (mxEv: MatrixEvent): Promise<string> => {
|
||||
const senderDisplayName = mxEv.sender && mxEv.sender.name ? mxEv.sender.name : mxEv.getSender();
|
||||
let mediaText = "";
|
||||
if (this.isAttachment(mxEv)) {
|
||||
|
@ -107,7 +107,7 @@ export default class PlainTextExporter extends Exporter {
|
|||
else return textForEvent(mxEv) + mediaText;
|
||||
};
|
||||
|
||||
protected async createOutput(events: MatrixEvent[]) {
|
||||
protected async createOutput(events: MatrixEvent[]): Promise<string> {
|
||||
let content = "";
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const event = events[i];
|
||||
|
@ -127,7 +127,7 @@ export default class PlainTextExporter extends Exporter {
|
|||
return content;
|
||||
}
|
||||
|
||||
public async export() {
|
||||
public async export(): Promise<void> {
|
||||
this.updateProgress(_t("Starting export process..."));
|
||||
this.updateProgress(_t("Fetching events..."));
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ import { AfterLeaveRoomPayload } from "../dispatcher/payloads/AfterLeaveRoomPayl
|
|||
import { bulkSpaceBehaviour } from "./space";
|
||||
import { SdkContextClass } from "../contexts/SDKContext";
|
||||
|
||||
export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = true) {
|
||||
export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = true): Promise<void> {
|
||||
let spinnerModal: IHandle<any>;
|
||||
if (spinner) {
|
||||
spinnerModal = Modal.createDialog(Spinner, null, "mx_Dialog_spinner");
|
||||
|
@ -65,7 +65,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
|
|||
.map(
|
||||
(ev) =>
|
||||
new Promise<void>((resolve, reject) => {
|
||||
const handler = () => {
|
||||
const handler = (): void => {
|
||||
if (ev.status === EventStatus.NOT_SENT) {
|
||||
spinnerModal?.close();
|
||||
reject(ev.error);
|
||||
|
@ -165,12 +165,12 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
|
|||
}
|
||||
}
|
||||
|
||||
export const leaveSpace = (space: Room) => {
|
||||
export const leaveSpace = (space: Room): void => {
|
||||
Modal.createDialog(
|
||||
LeaveSpaceDialog,
|
||||
{
|
||||
space,
|
||||
onFinished: async (leave: boolean, rooms: Room[]) => {
|
||||
onFinished: async (leave: boolean, rooms: Room[]): Promise<void> => {
|
||||
if (!leave) return;
|
||||
await bulkSpaceBehaviour(space, rooms, (room) => leaveRoomBehaviour(room.roomId));
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ export async function waitForRoomReadyAndApplyAfterCreateCallbacks(
|
|||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const finish = () => {
|
||||
const finish = (): void => {
|
||||
if (checkRoomStateIntervalHandle) clearInterval(checkRoomStateIntervalHandle);
|
||||
if (stopgapTimeoutHandle) clearTimeout(stopgapTimeoutHandle);
|
||||
|
||||
|
@ -97,7 +97,7 @@ export async function waitForRoomReadyAndApplyAfterCreateCallbacks(
|
|||
});
|
||||
};
|
||||
|
||||
const stopgapFinish = () => {
|
||||
const stopgapFinish = (): void => {
|
||||
logger.warn(`Assuming local room ${localRoom.roomId} is ready after hitting timeout`);
|
||||
finish();
|
||||
};
|
||||
|
|
|
@ -17,7 +17,8 @@ limitations under the License.
|
|||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
||||
import { RoomState, RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
|
||||
/**
|
||||
* Approximation of a membership status for a given room.
|
||||
|
@ -84,10 +85,15 @@ export function isJoinedOrNearlyJoined(membership: string): boolean {
|
|||
* NOTE: this assumes you've just created the room and there's not been an opportunity
|
||||
* for other code to run, so we shouldn't miss RoomState.newMember when it comes by.
|
||||
*/
|
||||
export async function waitForMember(client: MatrixClient, roomId: string, userId: string, opts = { timeout: 1500 }) {
|
||||
export async function waitForMember(
|
||||
client: MatrixClient,
|
||||
roomId: string,
|
||||
userId: string,
|
||||
opts = { timeout: 1500 },
|
||||
): Promise<boolean> {
|
||||
const { timeout } = opts;
|
||||
let handler;
|
||||
return new Promise((resolve) => {
|
||||
let handler: (event: MatrixEvent, state: RoomState, member: RoomMember) => void;
|
||||
return new Promise<boolean>((resolve) => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
handler = function (_, __, member: RoomMember) {
|
||||
if (member.userId !== userId) return;
|
||||
|
|
|
@ -56,7 +56,7 @@ export default class ElementPermalinkConstructor extends PermalinkConstructor {
|
|||
return testHost === (parsedUrl.host || parsedUrl.hostname); // one of the hosts should match
|
||||
}
|
||||
|
||||
public encodeServerCandidates(candidates?: string[]) {
|
||||
public encodeServerCandidates(candidates?: string[]): string {
|
||||
if (!candidates || candidates.length === 0) return "";
|
||||
return `?via=${candidates.map((c) => encodeURIComponent(c)).join("&via=")}`;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ export default class MatrixSchemePermalinkConstructor extends PermalinkConstruct
|
|||
return testHost === "";
|
||||
}
|
||||
|
||||
public encodeServerCandidates(candidates: string[]) {
|
||||
public encodeServerCandidates(candidates: string[]): string {
|
||||
if (!candidates || candidates.length === 0) return "";
|
||||
return `?via=${candidates.map((c) => encodeURIComponent(c)).join("&via=")}`;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ export default class MatrixToPermalinkConstructor extends PermalinkConstructor {
|
|||
return testHost === host;
|
||||
}
|
||||
|
||||
public encodeServerCandidates(candidates: string[]) {
|
||||
public encodeServerCandidates(candidates: string[]): string {
|
||||
if (!candidates || candidates.length === 0) return "";
|
||||
return `?via=${candidates.map((c) => encodeURIComponent(c)).join("&via=")}`;
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ export class RoomPermalinkCreator {
|
|||
}
|
||||
}
|
||||
|
||||
public load() {
|
||||
public load(): void {
|
||||
if (!this.room || !this.room.currentState) {
|
||||
// Under rare and unknown circumstances it is possible to have a room with no
|
||||
// currentState, at least potentially at the early stages of joining a room.
|
||||
|
@ -121,22 +121,22 @@ export class RoomPermalinkCreator {
|
|||
this.fullUpdate();
|
||||
}
|
||||
|
||||
public start() {
|
||||
public start(): void {
|
||||
this.load();
|
||||
this.room.currentState.on(RoomStateEvent.Update, this.onRoomStateUpdate);
|
||||
this.started = true;
|
||||
}
|
||||
|
||||
public stop() {
|
||||
public stop(): void {
|
||||
this.room.currentState.removeListener(RoomStateEvent.Update, this.onRoomStateUpdate);
|
||||
this.started = false;
|
||||
}
|
||||
|
||||
public get serverCandidates() {
|
||||
public get serverCandidates(): string[] {
|
||||
return this._serverCandidates;
|
||||
}
|
||||
|
||||
public isStarted() {
|
||||
public isStarted(): boolean {
|
||||
return this.started;
|
||||
}
|
||||
|
||||
|
@ -159,11 +159,11 @@ export class RoomPermalinkCreator {
|
|||
return getPermalinkConstructor().forRoom(this.roomId, this._serverCandidates);
|
||||
}
|
||||
|
||||
private onRoomStateUpdate = () => {
|
||||
private onRoomStateUpdate = (): void => {
|
||||
this.fullUpdate();
|
||||
};
|
||||
|
||||
private fullUpdate() {
|
||||
private fullUpdate(): void {
|
||||
// This updates the internal state of this object from the room state. It's broken
|
||||
// down into separate functions, previously because we did some of these as incremental
|
||||
// updates, but they were on member events which can be very numerous, so the incremental
|
||||
|
@ -175,7 +175,7 @@ export class RoomPermalinkCreator {
|
|||
this.updateServerCandidates();
|
||||
}
|
||||
|
||||
private updateHighestPlUser() {
|
||||
private updateHighestPlUser(): void {
|
||||
const plEvent = this.room.currentState.getStateEvents("m.room.power_levels", "");
|
||||
if (plEvent) {
|
||||
const content = plEvent.getContent();
|
||||
|
@ -215,13 +215,14 @@ export class RoomPermalinkCreator {
|
|||
this.highestPlUserId = null;
|
||||
}
|
||||
|
||||
private updateAllowedServers() {
|
||||
private updateAllowedServers(): void {
|
||||
const bannedHostsRegexps = [];
|
||||
let allowedHostsRegexps = [ANY_REGEX]; // default allow everyone
|
||||
if (this.room.currentState) {
|
||||
const aclEvent = this.room.currentState.getStateEvents(EventType.RoomServerAcl, "");
|
||||
if (aclEvent && aclEvent.getContent()) {
|
||||
const getRegex = (hostname) => new RegExp("^" + utils.globToRegexp(hostname, false) + "$");
|
||||
const getRegex = (hostname: string): RegExp =>
|
||||
new RegExp("^" + utils.globToRegexp(hostname, false) + "$");
|
||||
|
||||
const denied = aclEvent.getContent().deny || [];
|
||||
denied.forEach((h) => bannedHostsRegexps.push(getRegex(h)));
|
||||
|
@ -235,7 +236,7 @@ export class RoomPermalinkCreator {
|
|||
this.allowedHostsRegexps = allowedHostsRegexps;
|
||||
}
|
||||
|
||||
private updatePopulationMap() {
|
||||
private updatePopulationMap(): void {
|
||||
const populationMap: { [server: string]: number } = {};
|
||||
for (const member of this.room.getJoinedMembers()) {
|
||||
const serverName = getServerName(member.userId);
|
||||
|
@ -247,7 +248,7 @@ export class RoomPermalinkCreator {
|
|||
this.populationMap = populationMap;
|
||||
}
|
||||
|
||||
private updateServerCandidates = () => {
|
||||
private updateServerCandidates = (): void => {
|
||||
const candidates = new Set<string>();
|
||||
if (this.highestPlUserId) {
|
||||
candidates.add(getServerName(this.highestPlUserId));
|
||||
|
@ -474,7 +475,7 @@ function isHostnameIpAddress(hostname: string): boolean {
|
|||
return isIp(hostname);
|
||||
}
|
||||
|
||||
export const calculateRoomVia = (room: Room) => {
|
||||
export const calculateRoomVia = (room: Room): string[] => {
|
||||
const permalinkCreator = new RoomPermalinkCreator(room);
|
||||
permalinkCreator.load();
|
||||
return permalinkCreator.serverCandidates;
|
||||
|
|
|
@ -37,7 +37,7 @@ import { parsePermalink } from "./permalinks/Permalinks";
|
|||
* React components which have been mounted as part of this.
|
||||
* The initial caller should pass in an empty array to seed the accumulator.
|
||||
*/
|
||||
export function pillifyLinks(nodes: ArrayLike<Element>, mxEvent: MatrixEvent, pills: Element[]) {
|
||||
export function pillifyLinks(nodes: ArrayLike<Element>, mxEvent: MatrixEvent, pills: Element[]): void {
|
||||
const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId());
|
||||
const shouldShowPillAvatar = SettingsStore.getValue("Pill.shouldShowPillAvatar");
|
||||
let node = nodes[0];
|
||||
|
@ -148,7 +148,7 @@ export function pillifyLinks(nodes: ArrayLike<Element>, mxEvent: MatrixEvent, pi
|
|||
* @param {Element[]} pills - array of pill containers whose React
|
||||
* components should be unmounted.
|
||||
*/
|
||||
export function unmountPills(pills: Element[]) {
|
||||
export function unmountPills(pills: Element[]): void {
|
||||
for (const pillContainer of pills) {
|
||||
ReactDOM.unmountComponentAtNode(pillContainer);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||
import SdkConfig from "../SdkConfig";
|
||||
|
||||
export function isPresenceEnabled() {
|
||||
export function isPresenceEnabled(): boolean {
|
||||
const hsUrl = MatrixClientPeg.get().baseUrl;
|
||||
const urls = SdkConfig.get("enable_presence_by_hs_url");
|
||||
if (!urls) return true;
|
||||
|
|
|
@ -18,6 +18,7 @@ import React from "react";
|
|||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { RoomType, EventType } from "matrix-js-sdk/src/@types/event";
|
||||
import { JoinRule } from "matrix-js-sdk/src/@types/partials";
|
||||
import { ICreateRoomStateEvent } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { calculateRoomVia } from "./permalinks/Permalinks";
|
||||
import Modal from "../Modal";
|
||||
|
@ -39,7 +40,7 @@ import { OpenSpaceSettingsPayload } from "../dispatcher/payloads/OpenSpaceSettin
|
|||
import { OpenAddExistingToSpaceDialogPayload } from "../dispatcher/payloads/OpenAddExistingToSpaceDialogPayload";
|
||||
import { SdkContextClass } from "../contexts/SDKContext";
|
||||
|
||||
export const shouldShowSpaceSettings = (space: Room) => {
|
||||
export const shouldShowSpaceSettings = (space: Room): boolean => {
|
||||
const userId = space.client.getUserId();
|
||||
return (
|
||||
space.getMyMembership() === "join" &&
|
||||
|
@ -50,7 +51,7 @@ export const shouldShowSpaceSettings = (space: Room) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const makeSpaceParentEvent = (room: Room, canonical = false) => ({
|
||||
export const makeSpaceParentEvent = (room: Room, canonical = false): ICreateRoomStateEvent => ({
|
||||
type: EventType.SpaceParent,
|
||||
content: {
|
||||
via: calculateRoomVia(room),
|
||||
|
@ -59,7 +60,7 @@ export const makeSpaceParentEvent = (room: Room, canonical = false) => ({
|
|||
state_key: room.roomId,
|
||||
});
|
||||
|
||||
export function showSpaceSettings(space: Room) {
|
||||
export function showSpaceSettings(space: Room): void {
|
||||
defaultDispatcher.dispatch<OpenSpaceSettingsPayload>({
|
||||
action: Action.OpenSpaceSettings,
|
||||
space,
|
||||
|
@ -86,7 +87,7 @@ export const showCreateNewRoom = async (space: Room, type?: RoomType): Promise<b
|
|||
return shouldCreate;
|
||||
};
|
||||
|
||||
export const shouldShowSpaceInvite = (space: Room) =>
|
||||
export const shouldShowSpaceInvite = (space: Room): boolean =>
|
||||
((space?.getMyMembership() === "join" && space.canInvite(space.client.getUserId())) ||
|
||||
space.getJoinRule() === JoinRule.Public) &&
|
||||
shouldShowComponent(UIComponent.InviteUsers);
|
||||
|
@ -159,7 +160,7 @@ export const bulkSpaceBehaviour = async (
|
|||
}
|
||||
};
|
||||
|
||||
export const showSpacePreferences = (space: Room, initialTabId?: SpacePreferenceTab) => {
|
||||
export const showSpacePreferences = (space: Room, initialTabId?: SpacePreferenceTab): void => {
|
||||
defaultDispatcher.dispatch<OpenSpacePreferencesPayload>({
|
||||
action: Action.OpenSpacePreferences,
|
||||
space,
|
||||
|
|
|
@ -55,7 +55,7 @@ export async function copyPlaintext(text: string): Promise<boolean> {
|
|||
return false;
|
||||
}
|
||||
|
||||
export function selectText(target: Element) {
|
||||
export function selectText(target: Element): void {
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(target);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import LinkWithTooltip from "../components/views/elements/LinkWithTooltip";
|
|||
* React components that have been mounted by this function. The initial caller
|
||||
* should pass in an empty array to seed the accumulator.
|
||||
*/
|
||||
export function tooltipifyLinks(rootNodes: ArrayLike<Element>, ignoredNodes: Element[], containers: Element[]) {
|
||||
export function tooltipifyLinks(rootNodes: ArrayLike<Element>, ignoredNodes: Element[], containers: Element[]): void {
|
||||
if (!PlatformPeg.get()?.needsUrlTooltips()) {
|
||||
return;
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ export function tooltipifyLinks(rootNodes: ArrayLike<Element>, ignoredNodes: Ele
|
|||
*
|
||||
* @param {Element[]} containers - array of tooltip containers to unmount
|
||||
*/
|
||||
export function unmountTooltips(containers: Element[]) {
|
||||
export function unmountTooltips(containers: Element[]): void {
|
||||
for (const container of containers) {
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ interface TooltipEvents {
|
|||
export function useTooltip(props: ComponentProps<typeof Tooltip>): [TooltipEvents, JSX.Element | null] {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
const showTooltip = () => setIsVisible(true);
|
||||
const hideTooltip = () => setIsVisible(false);
|
||||
const showTooltip = (): void => setIsVisible(true);
|
||||
const hideTooltip = (): void => setIsVisible(false);
|
||||
|
||||
// No need to fill up the DOM with hidden tooltip elements. Only add the
|
||||
// tooltip when we're hovering over the item (performance)
|
||||
|
|
|
@ -19,6 +19,8 @@ limitations under the License.
|
|||
* - a number
|
||||
* - in a provided range (inclusive)
|
||||
*/
|
||||
export const validateNumberInRange = (min: number, max: number) => (value?: number) => {
|
||||
return typeof value === "number" && !(isNaN(value) || min > value || value > max);
|
||||
};
|
||||
export const validateNumberInRange =
|
||||
(min: number, max: number) =>
|
||||
(value?: number): boolean => {
|
||||
return typeof value === "number" && !(isNaN(value) || min > value || value > max);
|
||||
};
|
||||
|
|
|
@ -17,5 +17,5 @@ limitations under the License.
|
|||
import type { Room } from "matrix-js-sdk/src/models/room";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
|
||||
export const isVideoRoom = (room: Room) =>
|
||||
export const isVideoRoom = (room: Room): boolean =>
|
||||
room.isElementVideoRoom() || (SettingsStore.getValue("feature_element_call_video_rooms") && room.isCallRoom());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue