Convert bunch of utils to TS
This commit is contained in:
parent
5b72423ea3
commit
6d92953311
9 changed files with 120 additions and 98 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
Copyright 2019 - 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,36 +14,40 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
|
||||||
|
import { SerializedPart } from "../editor/parts";
|
||||||
|
import { Caret } from "../editor/caret";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used while editing, to pass the event, and to preserve editor state
|
* Used while editing, to pass the event, and to preserve editor state
|
||||||
* from one editor instance to another when remounting the editor
|
* from one editor instance to another when remounting the editor
|
||||||
* upon receiving the remote echo for an unsent event.
|
* upon receiving the remote echo for an unsent event.
|
||||||
*/
|
*/
|
||||||
export default class EditorStateTransfer {
|
export default class EditorStateTransfer {
|
||||||
constructor(event) {
|
private serializedParts: SerializedPart[] = null;
|
||||||
this._event = event;
|
private caret: Caret = null;
|
||||||
this._serializedParts = null;
|
|
||||||
this.caret = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
setEditorState(caret, serializedParts) {
|
constructor(private readonly event: MatrixEvent) {}
|
||||||
this._caret = caret;
|
|
||||||
this._serializedParts = serializedParts;
|
setEditorState(caret: Caret, serializedParts: SerializedPart[]) {
|
||||||
|
this.caret = caret;
|
||||||
|
this.serializedParts = serializedParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasEditorState() {
|
hasEditorState() {
|
||||||
return !!this._serializedParts;
|
return !!this.serializedParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSerializedParts() {
|
getSerializedParts() {
|
||||||
return this._serializedParts;
|
return this.serializedParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCaret() {
|
getCaret() {
|
||||||
return this._caret;
|
return this.caret;
|
||||||
}
|
}
|
||||||
|
|
||||||
getEvent() {
|
getEvent() {
|
||||||
return this._event;
|
return this.event;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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,7 +14,10 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { _t, _td } from '../languageHandler';
|
import React, { ReactNode } from "react";
|
||||||
|
import { MatrixError } from "matrix-js-sdk/src/http-api";
|
||||||
|
|
||||||
|
import { _t, _td, Tags, TranslatedString } from '../languageHandler';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a translated error message for a
|
* Produce a translated error message for a
|
||||||
|
@ -30,7 +33,12 @@ import { _t, _td } from '../languageHandler';
|
||||||
* for any tags in the strings apart from 'a'
|
* for any tags in the strings apart from 'a'
|
||||||
* @returns {*} Translated string or react component
|
* @returns {*} Translated string or react component
|
||||||
*/
|
*/
|
||||||
export function messageForResourceLimitError(limitType, adminContact, strings, extraTranslations) {
|
export function messageForResourceLimitError(
|
||||||
|
limitType: string,
|
||||||
|
adminContact: string,
|
||||||
|
strings: Record<string, string>,
|
||||||
|
extraTranslations?: Tags,
|
||||||
|
): TranslatedString {
|
||||||
let errString = strings[limitType];
|
let errString = strings[limitType];
|
||||||
if (errString === undefined) errString = strings[''];
|
if (errString === undefined) errString = strings[''];
|
||||||
|
|
||||||
|
@ -49,7 +57,7 @@ export function messageForResourceLimitError(limitType, adminContact, strings, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function messageForSyncError(err) {
|
export function messageForSyncError(err: MatrixError | Error): ReactNode {
|
||||||
if (err.errcode === 'M_RESOURCE_LIMIT_EXCEEDED') {
|
if (err.errcode === 'M_RESOURCE_LIMIT_EXCEEDED') {
|
||||||
const limitError = messageForResourceLimitError(
|
const limitError = messageForResourceLimitError(
|
||||||
err.data.limit_type,
|
err.data.limit_type,
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 New Vector Ltd
|
Copyright 2019 - 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,12 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EventStatus } from 'matrix-js-sdk/src/models/event';
|
import { Room } from 'matrix-js-sdk/src/models/room';
|
||||||
import {MatrixClientPeg} from '../MatrixClientPeg';
|
import { MatrixEvent, EventStatus } from 'matrix-js-sdk/src/models/event';
|
||||||
|
|
||||||
|
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||||
import shouldHideEvent from "../shouldHideEvent";
|
import shouldHideEvent from "../shouldHideEvent";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether an event should allow actions like reply, reactions, edit, etc.
|
* Returns whether an event should allow actions like reply, reactions, edit, etc.
|
||||||
* which effectively checks whether it's a regular message that has been sent and that we
|
* which effectively checks whether it's a regular message that has been sent and that we
|
||||||
|
@ -25,7 +28,7 @@ import shouldHideEvent from "../shouldHideEvent";
|
||||||
* @param {MatrixEvent} mxEvent The event to check
|
* @param {MatrixEvent} mxEvent The event to check
|
||||||
* @returns {boolean} true if actionable
|
* @returns {boolean} true if actionable
|
||||||
*/
|
*/
|
||||||
export function isContentActionable(mxEvent) {
|
export function isContentActionable(mxEvent: MatrixEvent): boolean {
|
||||||
const { status: eventStatus } = mxEvent;
|
const { status: eventStatus } = mxEvent;
|
||||||
|
|
||||||
// status is SENT before remote-echo, null after
|
// status is SENT before remote-echo, null after
|
||||||
|
@ -45,7 +48,7 @@ export function isContentActionable(mxEvent) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canEditContent(mxEvent) {
|
export function canEditContent(mxEvent: MatrixEvent): boolean {
|
||||||
if (mxEvent.status === EventStatus.CANCELLED || mxEvent.getType() !== "m.room.message" || mxEvent.isRedacted()) {
|
if (mxEvent.status === EventStatus.CANCELLED || mxEvent.getType() !== "m.room.message" || mxEvent.isRedacted()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +59,7 @@ export function canEditContent(mxEvent) {
|
||||||
mxEvent.getSender() === MatrixClientPeg.get().getUserId();
|
mxEvent.getSender() === MatrixClientPeg.get().getUserId();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canEditOwnEvent(mxEvent) {
|
export function canEditOwnEvent(mxEvent: MatrixEvent): boolean {
|
||||||
// for now we only allow editing
|
// for now we only allow editing
|
||||||
// your own events. So this just call through
|
// your own events. So this just call through
|
||||||
// In the future though, moderators will be able to
|
// In the future though, moderators will be able to
|
||||||
|
@ -67,7 +70,7 @@ export function canEditOwnEvent(mxEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_JUMP_DISTANCE = 100;
|
const MAX_JUMP_DISTANCE = 100;
|
||||||
export function findEditableEvent(room, isForward, fromEventId = undefined) {
|
export function findEditableEvent(room: Room, isForward: boolean, fromEventId: string = undefined): MatrixEvent {
|
||||||
const liveTimeline = room.getLiveTimeline();
|
const liveTimeline = room.getLiveTimeline();
|
||||||
const events = liveTimeline.getEvents().concat(room.getPendingEvents());
|
const events = liveTimeline.getEvents().concat(room.getPendingEvents());
|
||||||
const maxIdx = events.length - 1;
|
const maxIdx = events.length - 1;
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
Copyright 2019 - 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.
|
||||||
|
@ -15,14 +15,15 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SERVICE_TYPES } from 'matrix-js-sdk/src/service-types';
|
import { SERVICE_TYPES } from 'matrix-js-sdk/src/service-types';
|
||||||
|
|
||||||
import SdkConfig from '../SdkConfig';
|
import SdkConfig from '../SdkConfig';
|
||||||
import {MatrixClientPeg} from '../MatrixClientPeg';
|
import {MatrixClientPeg} from '../MatrixClientPeg';
|
||||||
|
|
||||||
export function getDefaultIdentityServerUrl() {
|
export function getDefaultIdentityServerUrl(): string {
|
||||||
return SdkConfig.get()['validated_server_config']['isUrl'];
|
return SdkConfig.get()['validated_server_config']['isUrl'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useDefaultIdentityServer() {
|
export function useDefaultIdentityServer(): void {
|
||||||
const url = getDefaultIdentityServerUrl();
|
const url = getDefaultIdentityServerUrl();
|
||||||
// Account data change will update localstorage, client, etc through dispatcher
|
// Account data change will update localstorage, client, etc through dispatcher
|
||||||
MatrixClientPeg.get().setAccountData("m.identity_server", {
|
MatrixClientPeg.get().setAccountData("m.identity_server", {
|
||||||
|
@ -30,7 +31,7 @@ export function useDefaultIdentityServer() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function doesIdentityServerHaveTerms(fullUrl) {
|
export async function doesIdentityServerHaveTerms(fullUrl: string): Promise<boolean> {
|
||||||
let terms;
|
let terms;
|
||||||
try {
|
try {
|
||||||
terms = await MatrixClientPeg.get().getTerms(SERVICE_TYPES.IS, fullUrl);
|
terms = await MatrixClientPeg.get().getTerms(SERVICE_TYPES.IS, fullUrl);
|
||||||
|
@ -46,7 +47,7 @@ export async function doesIdentityServerHaveTerms(fullUrl) {
|
||||||
return terms && terms["policies"] && (Object.keys(terms["policies"]).length > 0);
|
return terms && terms["policies"] && (Object.keys(terms["policies"]).length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doesAccountDataHaveIdentityServer() {
|
export function doesAccountDataHaveIdentityServer(): boolean {
|
||||||
const event = MatrixClientPeg.get().getAccountData("m.identity_server");
|
const event = MatrixClientPeg.get().getAccountData("m.identity_server");
|
||||||
return event && event.getContent() && event.getContent()['base_url'];
|
return event && event.getContent() && event.getContent()['base_url'];
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
Copyright 2019 - 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,31 +14,33 @@ 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 classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import DiffMatchPatch from 'diff-match-patch';
|
import { diff_match_patch as DiffMatchPatch } from 'diff-match-patch';
|
||||||
import {DiffDOM} from "diff-dom";
|
import { Action, DiffDOM, IDiff } from "diff-dom";
|
||||||
import { checkBlockNode, bodyToHtml } from "../HtmlUtils";
|
import { IContent } from "matrix-js-sdk/src/models/event";
|
||||||
|
|
||||||
|
import { bodyToHtml, checkBlockNode, IOptsReturnString } from "../HtmlUtils";
|
||||||
|
|
||||||
const decodeEntities = (function() {
|
const decodeEntities = (function() {
|
||||||
let textarea = null;
|
let textarea = null;
|
||||||
return function(string) {
|
return function(str: string): string {
|
||||||
if (!textarea) {
|
if (!textarea) {
|
||||||
textarea = document.createElement("textarea");
|
textarea = document.createElement("textarea");
|
||||||
}
|
}
|
||||||
textarea.innerHTML = string;
|
textarea.innerHTML = str;
|
||||||
return textarea.value;
|
return textarea.value;
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function textToHtml(text) {
|
function textToHtml(text: string): string {
|
||||||
const container = document.createElement("div");
|
const container = document.createElement("div");
|
||||||
container.textContent = text;
|
container.textContent = text;
|
||||||
return container.innerHTML;
|
return container.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSanitizedHtmlBody(content) {
|
function getSanitizedHtmlBody(content: IContent): string {
|
||||||
const opts = {
|
const opts: IOptsReturnString = {
|
||||||
stripReplyFallback: true,
|
stripReplyFallback: true,
|
||||||
returnString: true,
|
returnString: true,
|
||||||
};
|
};
|
||||||
|
@ -57,21 +59,21 @@ function getSanitizedHtmlBody(content) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapInsertion(child) {
|
function wrapInsertion(child: Node): HTMLElement {
|
||||||
const wrapper = document.createElement(checkBlockNode(child) ? "div" : "span");
|
const wrapper = document.createElement(checkBlockNode(child) ? "div" : "span");
|
||||||
wrapper.className = "mx_EditHistoryMessage_insertion";
|
wrapper.className = "mx_EditHistoryMessage_insertion";
|
||||||
wrapper.appendChild(child);
|
wrapper.appendChild(child);
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapDeletion(child) {
|
function wrapDeletion(child: Node): HTMLElement {
|
||||||
const wrapper = document.createElement(checkBlockNode(child) ? "div" : "span");
|
const wrapper = document.createElement(checkBlockNode(child) ? "div" : "span");
|
||||||
wrapper.className = "mx_EditHistoryMessage_deletion";
|
wrapper.className = "mx_EditHistoryMessage_deletion";
|
||||||
wrapper.appendChild(child);
|
wrapper.appendChild(child);
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findRefNodes(root, route, isAddition) {
|
function findRefNodes(root: Node, route: number[], isAddition = false) {
|
||||||
let refNode = root;
|
let refNode = root;
|
||||||
let refParentNode;
|
let refParentNode;
|
||||||
const end = isAddition ? route.length - 1 : route.length;
|
const end = isAddition ? route.length - 1 : route.length;
|
||||||
|
@ -79,7 +81,7 @@ function findRefNodes(root, route, isAddition) {
|
||||||
refParentNode = refNode;
|
refParentNode = refNode;
|
||||||
refNode = refNode.childNodes[route[i]];
|
refNode = refNode.childNodes[route[i]];
|
||||||
}
|
}
|
||||||
return {refNode, refParentNode};
|
return { refNode, refParentNode };
|
||||||
}
|
}
|
||||||
|
|
||||||
function diffTreeToDOM(desc) {
|
function diffTreeToDOM(desc) {
|
||||||
|
@ -101,7 +103,7 @@ function diffTreeToDOM(desc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function insertBefore(parent, nextSibling, child) {
|
function insertBefore(parent: Node, nextSibling: Node | null, child: Node): void {
|
||||||
if (nextSibling) {
|
if (nextSibling) {
|
||||||
parent.insertBefore(child, nextSibling);
|
parent.insertBefore(child, nextSibling);
|
||||||
} else {
|
} else {
|
||||||
|
@ -109,7 +111,7 @@ function insertBefore(parent, nextSibling, child) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRouteOfNextSibling(route1, route2) {
|
function isRouteOfNextSibling(route1: number[], route2: number[]): boolean {
|
||||||
// routes are arrays with indices,
|
// routes are arrays with indices,
|
||||||
// to be interpreted as a path in the dom tree
|
// to be interpreted as a path in the dom tree
|
||||||
|
|
||||||
|
@ -127,7 +129,7 @@ function isRouteOfNextSibling(route1, route2) {
|
||||||
return route2[lastD1Idx] >= route1[lastD1Idx];
|
return route2[lastD1Idx] >= route1[lastD1Idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
function adjustRoutes(diff, remainingDiffs) {
|
function adjustRoutes(diff: IDiff, remainingDiffs: IDiff[]): void {
|
||||||
if (diff.action === "removeTextElement" || diff.action === "removeElement") {
|
if (diff.action === "removeTextElement" || diff.action === "removeElement") {
|
||||||
// as removed text is not removed from the html, but marked as deleted,
|
// as removed text is not removed from the html, but marked as deleted,
|
||||||
// we need to readjust indices that assume the current node has been removed.
|
// we need to readjust indices that assume the current node has been removed.
|
||||||
|
@ -140,14 +142,14 @@ function adjustRoutes(diff, remainingDiffs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringAsTextNode(string) {
|
function stringAsTextNode(string: string): Text {
|
||||||
return document.createTextNode(decodeEntities(string));
|
return document.createTextNode(decodeEntities(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderDifferenceInDOM(originalRootNode, diff, diffMathPatch) {
|
function renderDifferenceInDOM(originalRootNode: Node, diff: IDiff, diffMathPatch: DiffMatchPatch): void {
|
||||||
const {refNode, refParentNode} = findRefNodes(originalRootNode, diff.route);
|
const {refNode, refParentNode} = findRefNodes(originalRootNode, diff.route);
|
||||||
switch (diff.action) {
|
switch (diff.action) {
|
||||||
case "replaceElement": {
|
case Action.ReplaceElement: {
|
||||||
const container = document.createElement("span");
|
const container = document.createElement("span");
|
||||||
const delNode = wrapDeletion(diffTreeToDOM(diff.oldValue));
|
const delNode = wrapDeletion(diffTreeToDOM(diff.oldValue));
|
||||||
const insNode = wrapInsertion(diffTreeToDOM(diff.newValue));
|
const insNode = wrapInsertion(diffTreeToDOM(diff.newValue));
|
||||||
|
@ -156,22 +158,22 @@ function renderDifferenceInDOM(originalRootNode, diff, diffMathPatch) {
|
||||||
refNode.parentNode.replaceChild(container, refNode);
|
refNode.parentNode.replaceChild(container, refNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "removeTextElement": {
|
case Action.RemoveTextElement: {
|
||||||
const delNode = wrapDeletion(stringAsTextNode(diff.value));
|
const delNode = wrapDeletion(stringAsTextNode(diff.value));
|
||||||
refNode.parentNode.replaceChild(delNode, refNode);
|
refNode.parentNode.replaceChild(delNode, refNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "removeElement": {
|
case Action.RemoveElement: {
|
||||||
const delNode = wrapDeletion(diffTreeToDOM(diff.element));
|
const delNode = wrapDeletion(diffTreeToDOM(diff.element));
|
||||||
refNode.parentNode.replaceChild(delNode, refNode);
|
refNode.parentNode.replaceChild(delNode, refNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "modifyTextElement": {
|
case Action.ModifyTextElement: {
|
||||||
const textDiffs = diffMathPatch.diff_main(diff.oldValue, diff.newValue);
|
const textDiffs = diffMathPatch.diff_main(diff.oldValue, diff.newValue);
|
||||||
diffMathPatch.diff_cleanupSemantic(textDiffs);
|
diffMathPatch.diff_cleanupSemantic(textDiffs);
|
||||||
const container = document.createElement("span");
|
const container = document.createElement("span");
|
||||||
for (const [modifier, text] of textDiffs) {
|
for (const [modifier, text] of textDiffs) {
|
||||||
let textDiffNode = stringAsTextNode(text);
|
let textDiffNode: Node = stringAsTextNode(text);
|
||||||
if (modifier < 0) {
|
if (modifier < 0) {
|
||||||
textDiffNode = wrapDeletion(textDiffNode);
|
textDiffNode = wrapDeletion(textDiffNode);
|
||||||
} else if (modifier > 0) {
|
} else if (modifier > 0) {
|
||||||
|
@ -182,12 +184,12 @@ function renderDifferenceInDOM(originalRootNode, diff, diffMathPatch) {
|
||||||
refNode.parentNode.replaceChild(container, refNode);
|
refNode.parentNode.replaceChild(container, refNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "addElement": {
|
case Action.AddElement: {
|
||||||
const insNode = wrapInsertion(diffTreeToDOM(diff.element));
|
const insNode = wrapInsertion(diffTreeToDOM(diff.element));
|
||||||
insertBefore(refParentNode, refNode, insNode);
|
insertBefore(refParentNode, refNode, insNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "addTextElement": {
|
case Action.AddTextElement: {
|
||||||
// XXX: sometimes diffDOM says insert a newline when there shouldn't be one
|
// 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.
|
// 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
|
// See https://github.com/fiduswriter/diffDOM/issues/100
|
||||||
|
@ -197,11 +199,11 @@ function renderDifferenceInDOM(originalRootNode, diff, diffMathPatch) {
|
||||||
}
|
}
|
||||||
// e.g. when changing a the href of a link,
|
// e.g. when changing a the href of a link,
|
||||||
// show the link with old href as removed and with the new href as added
|
// show the link with old href as removed and with the new href as added
|
||||||
case "removeAttribute":
|
case Action.RemoveAttribute:
|
||||||
case "addAttribute":
|
case Action.AddAttribute:
|
||||||
case "modifyAttribute": {
|
case Action.ModifyAttribute: {
|
||||||
const delNode = wrapDeletion(refNode.cloneNode(true));
|
const delNode = wrapDeletion(refNode.cloneNode(true));
|
||||||
const updatedNode = refNode.cloneNode(true);
|
const updatedNode = refNode.cloneNode(true) as HTMLElement;
|
||||||
if (diff.action === "addAttribute" || diff.action === "modifyAttribute") {
|
if (diff.action === "addAttribute" || diff.action === "modifyAttribute") {
|
||||||
updatedNode.setAttribute(diff.name, diff.newValue);
|
updatedNode.setAttribute(diff.name, diff.newValue);
|
||||||
} else {
|
} else {
|
||||||
|
@ -220,12 +222,12 @@ function renderDifferenceInDOM(originalRootNode, diff, diffMathPatch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function routeIsEqual(r1, r2) {
|
function routeIsEqual(r1: number[], r2: number[]): boolean {
|
||||||
return r1.length === r2.length && !r1.some((e, i) => e !== r2[i]);
|
return r1.length === r2.length && !r1.some((e, i) => e !== r2[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// workaround for https://github.com/fiduswriter/diffDOM/issues/90
|
// workaround for https://github.com/fiduswriter/diffDOM/issues/90
|
||||||
function filterCancelingOutDiffs(originalDiffActions) {
|
function filterCancelingOutDiffs(originalDiffActions: IDiff[]): IDiff[] {
|
||||||
const diffActions = originalDiffActions.slice();
|
const diffActions = originalDiffActions.slice();
|
||||||
|
|
||||||
for (let i = 0; i < diffActions.length; ++i) {
|
for (let i = 0; i < diffActions.length; ++i) {
|
||||||
|
@ -252,7 +254,7 @@ function filterCancelingOutDiffs(originalDiffActions) {
|
||||||
* @param {object} editContent the content for the edit message
|
* @param {object} editContent the content for the edit message
|
||||||
* @return {object} a react element similar to what `bodyToHtml` returns
|
* @return {object} a react element similar to what `bodyToHtml` returns
|
||||||
*/
|
*/
|
||||||
export function editBodyDiffToHtml(originalContent, editContent) {
|
export function editBodyDiffToHtml(originalContent: IContent, editContent: IContent): ReactNode {
|
||||||
// wrap the body in a div, DiffDOM needs a root element
|
// wrap the body in a div, DiffDOM needs a root element
|
||||||
const originalBody = `<div>${getSanitizedHtmlBody(originalContent)}</div>`;
|
const originalBody = `<div>${getSanitizedHtmlBody(originalContent)}</div>`;
|
||||||
const editBody = `<div>${getSanitizedHtmlBody(editContent)}</div>`;
|
const editBody = `<div>${getSanitizedHtmlBody(editContent)}</div>`;
|
|
@ -14,13 +14,15 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
|
||||||
export default class PinningUtils {
|
export default class PinningUtils {
|
||||||
/**
|
/**
|
||||||
* Determines if the given event may be pinned.
|
* Determines if the given event may be pinned.
|
||||||
* @param {MatrixEvent} event The event to check.
|
* @param {MatrixEvent} event The event to check.
|
||||||
* @return {boolean} True if the event may be pinned, false otherwise.
|
* @return {boolean} True if the event may be pinned, false otherwise.
|
||||||
*/
|
*/
|
||||||
static isPinnable(event) {
|
static isPinnable(event: MatrixEvent): boolean {
|
||||||
if (!event) return false;
|
if (!event) return false;
|
||||||
if (event.getType() !== "m.room.message") return false;
|
if (event.getType() !== "m.room.message") return false;
|
||||||
if (event.isRedacted()) return false;
|
if (event.isRedacted()) return false;
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 - 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,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given MatrixEvent containing receipts, return the first
|
* Given MatrixEvent containing receipts, return the first
|
||||||
* read receipt from the given user ID, or null if no such
|
* read receipt from the given user ID, or null if no such
|
||||||
|
@ -23,7 +25,7 @@ limitations under the License.
|
||||||
* @param {string} userId A user ID
|
* @param {string} userId A user ID
|
||||||
* @returns {Object} Read receipt
|
* @returns {Object} Read receipt
|
||||||
*/
|
*/
|
||||||
export function findReadReceiptFromUserId(receiptEvent, userId) {
|
export function findReadReceiptFromUserId(receiptEvent: MatrixEvent, userId: string): object | null {
|
||||||
const receiptKeys = Object.keys(receiptEvent.getContent());
|
const receiptKeys = Object.keys(receiptEvent.getContent());
|
||||||
for (let i = 0; i < receiptKeys.length; ++i) {
|
for (let i = 0; i < receiptKeys.length; ++i) {
|
||||||
const rcpt = receiptEvent.getContent()[receiptKeys[i]];
|
const rcpt = receiptEvent.getContent()[receiptKeys[i]];
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 New Vector Ltd
|
Copyright 2019 - 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.
|
||||||
|
@ -22,59 +22,58 @@ limitations under the License.
|
||||||
* Fires when the middle panel has been resized by a pixel.
|
* Fires when the middle panel has been resized by a pixel.
|
||||||
* @event module:utils~ResizeNotifier#"middlePanelResizedNoisy"
|
* @event module:utils~ResizeNotifier#"middlePanelResizedNoisy"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { throttle } from "lodash";
|
import { throttle } from "lodash";
|
||||||
|
|
||||||
export default class ResizeNotifier extends EventEmitter {
|
export default class ResizeNotifier extends EventEmitter {
|
||||||
constructor() {
|
private _isResizing = false;
|
||||||
super();
|
|
||||||
// with default options, will call fn once at first call, and then every x ms
|
// with default options, will call fn once at first call, and then every x ms
|
||||||
// if there was another call in that timespan
|
// if there was another call in that timespan
|
||||||
this._throttledMiddlePanel = throttle(() => this.emit("middlePanelResized"), 200);
|
private throttledMiddlePanel = throttle(() => this.emit("middlePanelResized"), 200);
|
||||||
this._isResizing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
get isResizing() {
|
public get isResizing() {
|
||||||
return this._isResizing;
|
return this._isResizing;
|
||||||
}
|
}
|
||||||
|
|
||||||
startResizing() {
|
public startResizing() {
|
||||||
this._isResizing = true;
|
this._isResizing = true;
|
||||||
this.emit("isResizing", true);
|
this.emit("isResizing", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
stopResizing() {
|
public stopResizing() {
|
||||||
this._isResizing = false;
|
this._isResizing = false;
|
||||||
this.emit("isResizing", false);
|
this.emit("isResizing", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
_noisyMiddlePanel() {
|
private noisyMiddlePanel() {
|
||||||
this.emit("middlePanelResizedNoisy");
|
this.emit("middlePanelResizedNoisy");
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateMiddlePanel() {
|
private updateMiddlePanel() {
|
||||||
this._throttledMiddlePanel();
|
this.throttledMiddlePanel();
|
||||||
this._noisyMiddlePanel();
|
this.noisyMiddlePanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// can be called in quick succession
|
// can be called in quick succession
|
||||||
notifyLeftHandleResized() {
|
public notifyLeftHandleResized() {
|
||||||
// don't emit event for own region
|
// don't emit event for own region
|
||||||
this._updateMiddlePanel();
|
this.updateMiddlePanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// can be called in quick succession
|
// can be called in quick succession
|
||||||
notifyRightHandleResized() {
|
public notifyRightHandleResized() {
|
||||||
this._updateMiddlePanel();
|
this.updateMiddlePanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyTimelineHeightChanged() {
|
public notifyTimelineHeightChanged() {
|
||||||
this._updateMiddlePanel();
|
this.updateMiddlePanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// can be called in quick succession
|
// can be called in quick succession
|
||||||
notifyWindowResized() {
|
public notifyWindowResized() {
|
||||||
this._updateMiddlePanel();
|
this.updateMiddlePanel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Vector Creations Ltd
|
Copyright 2017 - 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,10 +14,10 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {createClient} from "matrix-js-sdk/src/matrix";
|
import { createClient, ICreateClientOpts } from "matrix-js-sdk/src/matrix";
|
||||||
import {IndexedDBCryptoStore} from "matrix-js-sdk/src/crypto/store/indexeddb-crypto-store";
|
import { IndexedDBCryptoStore } from "matrix-js-sdk/src/crypto/store/indexeddb-crypto-store";
|
||||||
import {WebStorageSessionStore} from "matrix-js-sdk/src/store/session/webstorage";
|
import { WebStorageSessionStore } from "matrix-js-sdk/src/store/session/webstorage";
|
||||||
import {IndexedDBStore} from "matrix-js-sdk/src/store/indexeddb";
|
import { IndexedDBStore } from "matrix-js-sdk/src/store/indexeddb";
|
||||||
|
|
||||||
const localStorage = window.localStorage;
|
const localStorage = window.localStorage;
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ try {
|
||||||
*
|
*
|
||||||
* @returns {MatrixClient} the newly-created MatrixClient
|
* @returns {MatrixClient} the newly-created MatrixClient
|
||||||
*/
|
*/
|
||||||
export default function createMatrixClient(opts) {
|
export default function createMatrixClient(opts: ICreateClientOpts) {
|
||||||
const storeOpts = {
|
const storeOpts: Partial<ICreateClientOpts> = {
|
||||||
useAuthorizationHeader: true,
|
useAuthorizationHeader: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,9 +65,10 @@ export default function createMatrixClient(opts) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
opts = Object.assign(storeOpts, opts);
|
return createClient({
|
||||||
|
...storeOpts,
|
||||||
return createClient(opts);
|
...opts,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createMatrixClient.indexedDbWorkerScript = null;
|
createMatrixClient.indexedDbWorkerScript = null;
|
Loading…
Reference in a new issue