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

Finish sending pending messages before leaving room #7276

Merged
merged 1 commit into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1192,12 +1192,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
button: _t("Leave"),
onFinished: (shouldLeave) => {
if (shouldLeave) {
const d = leaveRoomBehaviour(roomId);
leaveRoomBehaviour(roomId);

// FIXME: controller shouldn't be loading a view :(
const modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');

d.finally(() => modal.close());
dis.dispatch({
action: "after_leave_room",
room_id: roomId,
Expand Down
35 changes: 32 additions & 3 deletions src/utils/membership.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ limitations under the License.

import { Room } from "matrix-js-sdk/src/models/room";
import { sleep } from "matrix-js-sdk/src/utils";
import { EventStatus } from "matrix-js-sdk/src/models/event";

import { MatrixClientPeg } from "../MatrixClientPeg";
import { _t } from "../languageHandler";
import Modal from "../Modal";
import Modal, { IHandle } from "../Modal";
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
import React from "react";
import dis from "../dispatcher/dispatcher";
import RoomViewStore from "../stores/RoomViewStore";
import Spinner from "../components/views/elements/Spinner";

/**
* Approximation of a membership status for a given room.
Expand Down Expand Up @@ -85,7 +87,12 @@ export function isJoinedOrNearlyJoined(membership: string): boolean {
return effective === EffectiveMembership.Join || effective === EffectiveMembership.Invite;
}

export async function leaveRoomBehaviour(roomId: string, retry = true) {
export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = true) {
let spinnerModal: IHandle<any>;
if (spinner) {
spinnerModal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');
}

const cli = MatrixClientPeg.get();
let leavingAllVersions = true;
const history = cli.getRoomUpgradeHistory(roomId);
Expand All @@ -98,6 +105,26 @@ export async function leaveRoomBehaviour(roomId: string, retry = true) {
}
}

const room = cli.getRoom(roomId);
// await any queued messages being sent so that they do not fail
await Promise.all(room.getPendingEvents().filter(ev => {
return [EventStatus.QUEUED, EventStatus.ENCRYPTING, EventStatus.SENDING].includes(ev.status);
}).map(ev => new Promise<void>((resolve, reject) => {
const handler = () => {
if (ev.status === EventStatus.NOT_SENT) {
spinnerModal?.close();
reject(ev.error);
}

if (!ev.status || ev.status === EventStatus.SENT) {
ev.off("Event.status", handler);
resolve();
}
};

ev.on("Event.status", handler);
})));

let results: { [roomId: string]: Error & { errcode?: string, message: string, data?: Record<string, any> } } = {};
if (!leavingAllVersions) {
try {
Expand All @@ -118,10 +145,12 @@ export async function leaveRoomBehaviour(roomId: string, retry = true) {
const limitExceededError = Object.values(results).find(e => e?.errcode === "M_LIMIT_EXCEEDED");
if (limitExceededError) {
await sleep(limitExceededError.data.retry_after_ms ?? 100);
return leaveRoomBehaviour(roomId, false);
return leaveRoomBehaviour(roomId, false, false);
}
}

spinnerModal?.close();

const errors = Object.entries(results).filter(r => !!r[1]);
if (errors.length > 0) {
const messages = [];
Expand Down