Convert ToastContainer and ToastStore to Typescript

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2020-05-22 12:47:40 +01:00
parent ac91304d8a
commit dc37469808
7 changed files with 98 additions and 79 deletions

View file

@ -120,6 +120,7 @@
"@types/classnames": "^2.2.10",
"@types/flux": "^3.1.9",
"@types/modernizr": "^3.5.3",
"@types/node": "^12.12.41",
"@types/qrcode": "^1.3.4",
"@types/react": "16.9",
"@types/zxcvbn": "^4.4.0",

View file

@ -15,6 +15,7 @@ limitations under the License.
*/
import * as ModernizrStatic from "modernizr";
import ToastStore from "../stores/ToastStore";
declare global {
interface Window {
@ -22,6 +23,8 @@ declare global {
Olm: {
init: () => Promise<void>;
};
mx_ToastStore: ToastStore;
}
// workaround for https://github.com/microsoft/TypeScript/issues/30933

View file

@ -1559,7 +1559,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
icon: "verification",
props: {request},
component: sdk.getComponent("toasts.VerificationRequestToast"),
priority: ToastStore.PRIORITY_REALTIME,
priority: 95,
});
}
});

View file

@ -16,13 +16,19 @@ limitations under the License.
import * as React from "react";
import { _t } from '../../languageHandler';
import ToastStore from "../../stores/ToastStore";
import ToastStore, {IToast} from "../../stores/ToastStore";
import classNames from "classnames";
export default class ToastContainer extends React.Component {
constructor() {
super();
this.state = {toasts: ToastStore.sharedInstance().getToasts()};
interface IState {
toasts: IToast<any>[];
}
export default class ToastContainer extends React.Component<{}, IState> {
constructor(props, context) {
super(props, context);
this.state = {
toasts: ToastStore.sharedInstance().getToasts(),
};
// Start listening here rather than in componentDidMount because
// toasts may dismiss themselves in their didMount if they find

View file

@ -1,73 +0,0 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import EventEmitter from 'events';
/**
* Holds the active toasts
*/
export default class ToastStore extends EventEmitter {
static PRIORITY_REALTIME = 0;
static PRIORITY_DEFAULT = 1;
static PRIORITY_LOW = 2;
static sharedInstance() {
if (!global.mx_ToastStore) global.mx_ToastStore = new ToastStore();
return global.mx_ToastStore;
}
constructor() {
super();
this._dispatcherRef = null;
this._toasts = [];
}
reset() {
this._toasts = [];
}
/**
* Add or replace a toast
* If a toast with the same toastKey already exists, the given toast will replace it
* Toasts are always added underneath any toasts of the same priority, so existing
* toasts stay at the top unless a higher priority one arrives (better to not change the
* toast unless necessary).
*
* @param {boject} newToast The new toast
*/
addOrReplaceToast(newToast) {
if (newToast.priority === undefined) newToast.priority = ToastStore.PRIORITY_DEFAULT;
const oldIndex = this._toasts.findIndex(t => t.key === newToast.key);
if (oldIndex === -1) {
let newIndex = this._toasts.length;
while (newIndex > 0 && this._toasts[newIndex - 1].priority > newToast.priority) --newIndex;
this._toasts.splice(newIndex, 0, newToast);
} else {
this._toasts[oldIndex] = newToast;
}
this.emit('update');
}
dismissToast(key) {
this._toasts = this._toasts.filter(t => t.key !== key);
this.emit('update');
}
getToasts() {
return this._toasts;
}
}

77
src/stores/ToastStore.ts Normal file
View file

@ -0,0 +1,77 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import EventEmitter from "events";
import React, {JSXElementConstructor} from "react";
export interface IToast<C extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> {
key: string;
// higher priority number will be shown on top of lower priority
priority: number;
title: string;
icon?: string;
component: C;
props?: React.ComponentProps<C>;
}
/**
* Holds the active toasts
*/
export default class ToastStore extends EventEmitter {
private toasts: IToast<any>[] = [];
static sharedInstance() {
if (!window.mx_ToastStore) window.mx_ToastStore = new ToastStore();
return window.mx_ToastStore;
}
reset() {
this.toasts = [];
}
/**
* Add or replace a toast
* If a toast with the same toastKey already exists, the given toast will replace it
* Toasts are always added underneath any toasts of the same priority, so existing
* toasts stay at the top unless a higher priority one arrives (better to not change the
* toast unless necessary).
*
* @param {object} newToast The new toast
*/
addOrReplaceToast<C extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>>(newToast: IToast<C>) {
const oldIndex = this.toasts.findIndex(t => t.key === newToast.key);
if (oldIndex === -1) {
let newIndex = this.toasts.length;
while (newIndex > 0 && this.toasts[newIndex - 1].priority > newToast.priority) --newIndex;
this.toasts.splice(newIndex, 0, newToast);
} else {
this.toasts[oldIndex] = newToast;
}
this.emit('update');
}
dismissToast(key) {
const length = this.toasts.length;
this.toasts = this.toasts.filter(t => t.key !== key);
if (length !== this.toasts.length) {
this.emit('update');
}
}
getToasts() {
return this.toasts;
}
}

View file

@ -1280,6 +1280,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b"
integrity sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ==
"@types/node@^12.12.41":
version "12.12.42"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.42.tgz#d0d1149336bd07540dd1ea576692829d575dec34"
integrity sha512-R/9QdYFLL9dE9l5cWWzWIZByVGFd7lk7JVOJ7KD+E1SJ4gni7XJRLz9QTjyYQiHIqEAgku9VgxdLjMlhhUaAFg==
"@types/prop-types@*":
version "15.7.3"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"