Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Convert RoomStatusBar to TS
Browse files Browse the repository at this point in the history
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
  • Loading branch information
SimonBrandner committed Sep 12, 2021
1 parent 63f1b7f commit 316f3b2
Showing 1 changed file with 79 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,95 +15,107 @@ limitations under the License.
*/

import React from 'react';
import PropTypes from 'prop-types';
import { _t, _td } from '../../languageHandler';
import { MatrixClientPeg } from '../../MatrixClientPeg';
import Resend from '../../Resend';
import dis from '../../dispatcher/dispatcher';
import { messageForResourceLimitError } from '../../utils/ErrorUtils';
import { Action } from "../../dispatcher/actions";
import { replaceableComponent } from "../../utils/replaceableComponent";
import { EventStatus } from "matrix-js-sdk/src/models/event";
import { EventStatus, MatrixEvent } from "matrix-js-sdk/src/models/event";
import NotificationBadge from "../views/rooms/NotificationBadge";
import { StaticNotificationState } from "../../stores/notifications/StaticNotificationState";
import AccessibleButton from "../views/elements/AccessibleButton";
import InlineSpinner from "../views/elements/InlineSpinner";
import { SyncState } from "matrix-js-sdk/src/sync.api";
import { ISyncStateData } from "matrix-js-sdk/src/sync";
import { Room } from "matrix-js-sdk/src/models/room";

const STATUS_BAR_HIDDEN = 0;
const STATUS_BAR_EXPANDED = 1;
const STATUS_BAR_EXPANDED_LARGE = 2;

export function getUnsentMessages(room) {
export function getUnsentMessages(room: Room): MatrixEvent[] {
if (!room) { return []; }
return room.getPendingEvents().filter(function(ev) {
return ev.status === EventStatus.NOT_SENT;
});
}

@replaceableComponent("structures.RoomStatusBar")
export default class RoomStatusBar extends React.PureComponent {
static propTypes = {
// the room this statusbar is representing.
room: PropTypes.object.isRequired,

// true if the room is being peeked at. This affects components that shouldn't
// logically be shown when peeking, such as a prompt to invite people to a room.
isPeeking: PropTypes.bool,

// callback for when the user clicks on the 'resend all' button in the
// 'unsent messages' bar
onResendAllClick: PropTypes.func,

// callback for when the user clicks on the 'cancel all' button in the
// 'unsent messages' bar
onCancelAllClick: PropTypes.func,

// callback for when the user clicks on the 'invite others' button in the
// 'you are alone' bar
onInviteClick: PropTypes.func,

// callback for when we do something that changes the size of the
// status bar. This is used to trigger a re-layout in the parent
// component.
onResize: PropTypes.func,

// callback for when the status bar can be hidden from view, as it is
// not displaying anything
onHidden: PropTypes.func,

// callback for when the status bar is displaying something and should
// be visible
onVisible: PropTypes.func,
};
interface IProps {
// the room this statusbar is representing.
room: Room;

// true if the room is being peeked at. This affects components that shouldn't
// logically be shown when peeking, such as a prompt to invite people to a room.
isPeeking?: boolean;
// callback for when the user clicks on the 'resend all' button in the
// 'unsent messages' bar
onResendAllClick?: () => void;

// callback for when the user clicks on the 'cancel all' button in the
// 'unsent messages' bar
onCancelAllClick?: () => void;

// callback for when the user clicks on the 'invite others' button in the
// 'you are alone' bar
onInviteClick?: () => void;

// callback for when we do something that changes the size of the
// status bar. This is used to trigger a re-layout in the parent
// component.
onResize?: () => void;

// callback for when the status bar can be hidden from view, as it is
// not displaying anything
onHidden?: () => void;

// callback for when the status bar is displaying something and should
// be visible
onVisible?: () => void;
}

state = {
syncState: MatrixClientPeg.get().getSyncState(),
syncStateData: MatrixClientPeg.get().getSyncStateData(),
unsentMessages: getUnsentMessages(this.props.room),
isResending: false,
};
interface IState {
syncState: SyncState;
syncStateData: ISyncStateData;
unsentMessages: MatrixEvent[];
isResending: boolean;
}

@replaceableComponent("structures.RoomStatusBar")
export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
constructor(props: IProps) {
super(props);

this.state = {
syncState: MatrixClientPeg.get().getSyncState(),
syncStateData: MatrixClientPeg.get().getSyncStateData(),
unsentMessages: getUnsentMessages(this.props.room),
isResending: false,
};
}

componentDidMount() {
public componentDidMount(): void {
MatrixClientPeg.get().on("sync", this.onSyncStateChange);
MatrixClientPeg.get().on("Room.localEchoUpdated", this._onRoomLocalEchoUpdated);
MatrixClientPeg.get().on("Room.localEchoUpdated", this.onRoomLocalEchoUpdated);

this._checkSize();
this.checkSize();
}

componentDidUpdate() {
this._checkSize();
public componentDidUpdate(): void {
this.checkSize();
}

componentWillUnmount() {
public componentWillUnmount(): void {
// we may have entirely lost our client as we're logging out before clicking login on the guest bar...
const client = MatrixClientPeg.get();
if (client) {
client.removeListener("sync", this.onSyncStateChange);
client.removeListener("Room.localEchoUpdated", this._onRoomLocalEchoUpdated);
client.removeListener("Room.localEchoUpdated", this.onRoomLocalEchoUpdated);
}
}

onSyncStateChange = (state, prevState, data) => {
private onSyncStateChange = (state: SyncState, prevState: SyncState, data: ISyncStateData): void => {
if (state === "SYNCING" && prevState === "SYNCING") {
return;
}
Expand All @@ -113,20 +125,20 @@ export default class RoomStatusBar extends React.PureComponent {
});
};

_onResendAllClick = () => {
private onResendAllClick = (): void => {
Resend.resendUnsentEvents(this.props.room).then(() => {
this.setState({ isResending: false });
});
this.setState({ isResending: true });
dis.fire(Action.FocusSendMessageComposer);
};

_onCancelAllClick = () => {
private onCancelAllClick = (): void => {
Resend.cancelUnsentEvents(this.props.room);
dis.fire(Action.FocusSendMessageComposer);
};

_onRoomLocalEchoUpdated = (event, room, oldEventId, oldStatus) => {
private onRoomLocalEchoUpdated = (ev: MatrixEvent, room: Room) => {
if (room.roomId !== this.props.room.roomId) return;
const messages = getUnsentMessages(this.props.room);
this.setState({
Expand All @@ -136,8 +148,8 @@ export default class RoomStatusBar extends React.PureComponent {
};

// Check whether current size is greater than 0, if yes call props.onVisible
_checkSize() {
if (this._getSize()) {
private checkSize(): void {
if (this.getSize()) {
if (this.props.onVisible) this.props.onVisible();
} else {
if (this.props.onHidden) this.props.onHidden();
Expand All @@ -147,29 +159,29 @@ export default class RoomStatusBar extends React.PureComponent {
// We don't need the actual height - just whether it is likely to have
// changed - so we use '0' to indicate normal size, and other values to
// indicate other sizes.
_getSize() {
if (this._shouldShowConnectionError()) {
private getSize(): number {
if (this.shouldShowConnectionError()) {
return STATUS_BAR_EXPANDED;
} else if (this.state.unsentMessages.length > 0 || this.state.isResending) {
return STATUS_BAR_EXPANDED_LARGE;
}
return STATUS_BAR_HIDDEN;
}

_shouldShowConnectionError() {
private shouldShowConnectionError(): boolean {
// no conn bar trumps the "some not sent" msg since you can't resend without
// a connection!
// There's one situation in which we don't show this 'no connection' bar, and that's
// if it's a resource limit exceeded error: those are shown in the top bar.
const errorIsMauError = Boolean(
this.state.syncStateData &&
this.state.syncStateData.error &&
this.state.syncStateData.error.errcode === 'M_RESOURCE_LIMIT_EXCEEDED',
this.state.syncStateData.error.name === 'M_RESOURCE_LIMIT_EXCEEDED',
);
return this.state.syncState === "ERROR" && !errorIsMauError;
}

_getUnsentMessageContent() {
private getUnsentMessageContent(): JSX.Element {
const unsentMessages = this.state.unsentMessages;

let title;
Expand Down Expand Up @@ -221,10 +233,10 @@ export default class RoomStatusBar extends React.PureComponent {
}

let buttonRow = <>
<AccessibleButton onClick={this._onCancelAllClick} className="mx_RoomStatusBar_unsentCancelAllBtn">
<AccessibleButton onClick={this.onCancelAllClick} className="mx_RoomStatusBar_unsentCancelAllBtn">
{ _t("Delete all") }
</AccessibleButton>
<AccessibleButton onClick={this._onResendAllClick} className="mx_RoomStatusBar_unsentResendAllBtn">
<AccessibleButton onClick={this.onResendAllClick} className="mx_RoomStatusBar_unsentResendAllBtn">
{ _t("Retry all") }
</AccessibleButton>
</>;
Expand Down Expand Up @@ -260,8 +272,8 @@ export default class RoomStatusBar extends React.PureComponent {
</>;
}

render() {
if (this._shouldShowConnectionError()) {
public render(): JSX.Element {
if (this.shouldShowConnectionError()) {
return (
<div className="mx_RoomStatusBar">
<div role="alert">
Expand All @@ -287,7 +299,7 @@ export default class RoomStatusBar extends React.PureComponent {
}

if (this.state.unsentMessages.length > 0 || this.state.isResending) {
return this._getUnsentMessageContent();
return this.getUnsentMessageContent();
}

return null;
Expand Down

0 comments on commit 316f3b2

Please sign in to comment.