From cd98106afbc603bd7bc1495a4ddc056cf1357a82 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 24 Mar 2022 16:30:53 -0600 Subject: [PATCH] Step 8.5: Move call transfer invite dialog construction --- src/CallHandler.tsx | 24 ++++++---- src/RoomInvite.tsx | 3 +- src/components/views/dialogs/InviteDialog.tsx | 33 +------------ .../views/dialogs/InviteDialogTypes.ts | 47 +++++++++++++++++++ src/dispatcher/actions.ts | 5 ++ .../payloads/OpenInviteDialogPayload.ts | 37 +++++++++++++++ src/utils/DialogOpener.ts | 10 ++++ 7 files changed, 117 insertions(+), 42 deletions(-) create mode 100644 src/components/views/dialogs/InviteDialogTypes.ts create mode 100644 src/dispatcher/payloads/OpenInviteDialogPayload.ts diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index a8082e668b..8e197e900f 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -44,7 +44,6 @@ import { WidgetType } from "./widgets/WidgetType"; import { SettingLevel } from "./settings/SettingLevel"; import QuestionDialog from "./components/views/dialogs/QuestionDialog"; import ErrorDialog from "./components/views/dialogs/ErrorDialog"; -import InviteDialog, { KIND_CALL_TRANSFER } from "./components/views/dialogs/InviteDialog"; import WidgetStore from "./stores/WidgetStore"; import { WidgetMessagingStore } from "./stores/widgets/WidgetMessagingStore"; import { ElementWidgetActions } from "./stores/widgets/ElementWidgetActions"; @@ -61,6 +60,8 @@ import ToastStore from './stores/ToastStore'; import Resend from './Resend'; import { ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload"; import { findDMForUser } from "./utils/direct-messages"; +import { KIND_CALL_TRANSFER } from "./components/views/dialogs/InviteDialogTypes"; +import { OpenInviteDialogPayload } from "./dispatcher/payloads/OpenInviteDialogPayload"; export const PROTOCOL_PSTN = 'm.protocol.pstn'; export const PROTOCOL_PSTN_PREFIXED = 'im.vector.protocol.pstn'; @@ -1092,15 +1093,18 @@ export default class CallHandler extends EventEmitter { */ public showTransferDialog(call: MatrixCall): void { call.setRemoteOnHold(true); - const { finished } = Modal.createTrackedDialog( - 'Transfer Call', '', InviteDialog, { kind: KIND_CALL_TRANSFER, call }, - /*className=*/"mx_InviteDialog_transferWrapper", /*isPriority=*/false, /*isStatic=*/true, - ); - finished.then((results: boolean[]) => { - if (results.length === 0 || results[0] === false) { - call.setRemoteOnHold(false); - } - }); + dis.dispatch({ + action: Action.OpenInviteDialog, + kind: KIND_CALL_TRANSFER, + call, + analyticsName: "Transfer Call", + className: "mx_InviteDialog_transferWrapper", + onFinishedCallback: (results) => { + if (results.length === 0 || results[0] === false) { + call.setRemoteOnHold(false); + } + }, + } as OpenInviteDialogPayload); } private addCallForRoom(roomId: string, call: MatrixCall, changedRooms = false): void { diff --git a/src/RoomInvite.tsx b/src/RoomInvite.tsx index fae3f5dfeb..8abfc5ce39 100644 --- a/src/RoomInvite.tsx +++ b/src/RoomInvite.tsx @@ -24,10 +24,11 @@ import { MatrixClientPeg } from './MatrixClientPeg'; import MultiInviter, { CompletionStates } from './utils/MultiInviter'; import Modal from './Modal'; import { _t } from './languageHandler'; -import InviteDialog, { KIND_DM, KIND_INVITE, Member } from "./components/views/dialogs/InviteDialog"; +import InviteDialog from "./components/views/dialogs/InviteDialog"; import BaseAvatar from "./components/views/avatars/BaseAvatar"; import { mediaFromMxc } from "./customisations/Media"; import ErrorDialog from "./components/views/dialogs/ErrorDialog"; +import { KIND_DM, KIND_INVITE, Member } from "./components/views/dialogs/InviteDialogTypes"; export interface IInviteResult { states: CompletionStates; diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx index 23a8549343..ed79958e3c 100644 --- a/src/components/views/dialogs/InviteDialog.tsx +++ b/src/components/views/dialogs/InviteDialog.tsx @@ -66,6 +66,7 @@ import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; import { getKeyBindingsManager } from "../../../KeyBindingsManager"; import { privateShouldBeEncrypted } from "../../../utils/rooms"; import { findDMForUser } from "../../../utils/direct-messages"; +import { AnyInviteKind, KIND_CALL_TRANSFER, KIND_DM, KIND_INVITE, Member } from './InviteDialogTypes'; // we have a number of types defined from the Matrix spec which can't reasonably be altered here. /* eslint-disable camelcase */ @@ -76,13 +77,6 @@ interface IRecentUser { lastActive: number; } -export const KIND_DM = "dm"; -export const KIND_INVITE = "invite"; -// NB. This dialog needs the 'mx_InviteDialog_transferWrapper' wrapper class to have the correct -// padding on the bottom (because all modals have 24px padding on all sides), so this needs to -// be passed when creating the modal -export const KIND_CALL_TRANSFER = "call_transfer"; - const INITIAL_ROOMS_SHOWN = 3; // Number of rooms to show at first const INCREMENT_ROOMS_SHOWN = 5; // Number of rooms to add when 'show more' is clicked @@ -91,29 +85,6 @@ enum TabId { DialPad = 'dialpad', } -// This is the interface that is expected by various components in the Invite Dialog and RoomInvite. -// It is a bit awkward because it also matches the RoomMember class from the js-sdk with some extra support -// for 3PIDs/email addresses. -export abstract class Member { - /** - * The display name of this Member. For users this should be their profile's display - * name or user ID if none set. For 3PIDs this should be the 3PID address (email). - */ - public abstract get name(): string; - - /** - * The ID of this Member. For users this should be their user ID. For 3PIDs this should - * be the 3PID address (email). - */ - public abstract get userId(): string; - - /** - * Gets the MXC URL of this Member's avatar. For users this should be their profile's - * avatar MXC URL or null if none set. For 3PIDs this should always be null. - */ - public abstract getMxcAvatarUrl(): string; -} - class DirectoryMember extends Member { private readonly _userId: string; private readonly displayName?: string; @@ -352,7 +323,7 @@ interface IInviteDialogProps { // The kind of invite being performed. Assumed to be KIND_DM if // not provided. - kind: string; + kind: AnyInviteKind; // The room ID this dialog is for. Only required for KIND_INVITE. roomId: string; diff --git a/src/components/views/dialogs/InviteDialogTypes.ts b/src/components/views/dialogs/InviteDialogTypes.ts new file mode 100644 index 0000000000..e9ec7f4927 --- /dev/null +++ b/src/components/views/dialogs/InviteDialogTypes.ts @@ -0,0 +1,47 @@ +/* +Copyright 2022 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. +*/ + +export const KIND_DM = "dm"; +export const KIND_INVITE = "invite"; +// NB. This dialog needs the 'mx_InviteDialog_transferWrapper' wrapper class to have the correct +// padding on the bottom (because all modals have 24px padding on all sides), so this needs to +// be passed when creating the modal +export const KIND_CALL_TRANSFER = "call_transfer"; + +export type AnyInviteKind = typeof KIND_INVITE | typeof KIND_DM | typeof KIND_CALL_TRANSFER; + +// This is the interface that is expected by various components in the Invite Dialog and RoomInvite. +// It is a bit awkward because it also matches the RoomMember class from the js-sdk with some extra support +// for 3PIDs/email addresses. +export abstract class Member { + /** + * The display name of this Member. For users this should be their profile's display + * name or user ID if none set. For 3PIDs this should be the 3PID address (email). + */ + public abstract get name(): string; + + /** + * The ID of this Member. For users this should be their user ID. For 3PIDs this should + * be the 3PID address (email). + */ + public abstract get userId(): string; + + /** + * Gets the MXC URL of this Member's avatar. For users this should be their profile's + * avatar MXC URL or null if none set. For 3PIDs this should always be null. + */ + public abstract getMxcAvatarUrl(): string; +} diff --git a/src/dispatcher/actions.ts b/src/dispatcher/actions.ts index 647dea43bf..496faa4661 100644 --- a/src/dispatcher/actions.ts +++ b/src/dispatcher/actions.ts @@ -302,4 +302,9 @@ export enum Action { * Opens the settings for the given space. Used with a OpenSpaceSettingsPayload. */ OpenSpaceSettings = "open_space_settings", + + /** + * Opens the invite dialog. Used with a OpenInviteDialogPayload. + */ + OpenInviteDialog = "open_invite_dialog", } diff --git a/src/dispatcher/payloads/OpenInviteDialogPayload.ts b/src/dispatcher/payloads/OpenInviteDialogPayload.ts new file mode 100644 index 0000000000..286781a45a --- /dev/null +++ b/src/dispatcher/payloads/OpenInviteDialogPayload.ts @@ -0,0 +1,37 @@ +/* +Copyright 2022 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 { Optional } from "matrix-events-sdk"; +import { MatrixCall } from "matrix-js-sdk/src/webrtc/call"; + +import { ActionPayload } from "../payloads"; +import { Action } from "../actions"; +import { + AnyInviteKind, +} from "../../components/views/dialogs/InviteDialogTypes"; + +export interface OpenInviteDialogPayload extends ActionPayload { + action: Action.OpenInviteDialog; + + kind: AnyInviteKind; + onFinishedCallback: Optional<(results: boolean[]) => void>; + + call?: MatrixCall; + roomId?: string; + + analyticsName: string; + className: string; +} diff --git a/src/utils/DialogOpener.ts b/src/utils/DialogOpener.ts index dfba761410..1c3d8c3e8d 100644 --- a/src/utils/DialogOpener.ts +++ b/src/utils/DialogOpener.ts @@ -26,6 +26,7 @@ import ReportEventDialog from "../components/views/dialogs/ReportEventDialog"; import TabbedIntegrationManagerDialog from "../components/views/dialogs/TabbedIntegrationManagerDialog"; import SpacePreferencesDialog from "../components/views/dialogs/SpacePreferencesDialog"; import SpaceSettingsDialog from "../components/views/dialogs/SpaceSettingsDialog"; +import InviteDialog from "../components/views/dialogs/InviteDialog"; /** * Auxiliary class to listen for dialog opening over the dispatcher and @@ -91,6 +92,15 @@ export class DialogOpener { space: payload.space, }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); break; + case Action.OpenInviteDialog: + Modal.createTrackedDialog(payload.analyticsName, '', InviteDialog, { + kind: payload.kind, + call: payload.call, + roomId: payload.roomId, + }, payload.className, false, true).finished.then((results) => { + payload.onFinishedCallback?.(results); + }); + break; } }; }