Convert view_user dispatch to prove the conversion works
This is a relatively obvious dispatch action that doesn't require a lot of complicated type definitions, so should be a good candidate to prove the thing works. If for some reason the thing stops working, we've done something wrong. This also adds a bit of generic types to the dispatch call so we don't confuse the tsx parser by using `dis.dispatch(<ViewUserPayload>{...})` as it thinks that's supposed to be a component. We still get type safety, and the thing remains happy with the generics approach.
This commit is contained in:
parent
a3b4c2dfa0
commit
a5f3318f3b
14 changed files with 88 additions and 30 deletions
|
@ -41,6 +41,8 @@ import { parseFragment as parseHtml } from "parse5";
|
|||
import sendBugReport from "./rageshake/submit-rageshake";
|
||||
import SdkConfig from "./SdkConfig";
|
||||
import { ensureDMExists } from "./createRoom";
|
||||
import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload";
|
||||
import { Action } from "./dispatcher/actions";
|
||||
|
||||
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
|
||||
interface HTMLInputEvent extends Event {
|
||||
|
@ -943,8 +945,10 @@ export const Commands = [
|
|||
}
|
||||
|
||||
const member = MatrixClientPeg.get().getRoom(roomId).getMember(userId);
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
dis.dispatch<ViewUserPayload>({
|
||||
action: Action.ViewUser,
|
||||
// XXX: We should be using a real member object and not assuming what the
|
||||
// receiver wants.
|
||||
member: member || {userId},
|
||||
});
|
||||
return success();
|
||||
|
|
|
@ -17,12 +17,11 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, {createRef} from 'react';
|
||||
import {InvalidStoreError} from "matrix-js-sdk/src/errors";
|
||||
import {RoomMember} from "matrix-js-sdk/src/models/room-member";
|
||||
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
|
||||
import React, { createRef } from 'react';
|
||||
import { InvalidStoreError } from "matrix-js-sdk/src/errors";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { isCryptoAvailable } from 'matrix-js-sdk/src/crypto';
|
||||
|
||||
// focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss
|
||||
import 'focus-visible';
|
||||
// what-input helps improve keyboard accessibility
|
||||
|
@ -30,7 +29,7 @@ import 'what-input';
|
|||
|
||||
import Analytics from "../../Analytics";
|
||||
import { DecryptionFailureTracker } from "../../DecryptionFailureTracker";
|
||||
import {MatrixClientPeg} from "../../MatrixClientPeg";
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import PlatformPeg from "../../PlatformPeg";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
import * as RoomListSorter from "../../RoomListSorter";
|
||||
|
@ -40,7 +39,7 @@ import Notifier from '../../Notifier';
|
|||
import Modal from "../../Modal";
|
||||
import Tinter from "../../Tinter";
|
||||
import * as sdk from '../../index';
|
||||
import { showStartChatInviteDialog, showRoomInviteDialog } from '../../RoomInvite';
|
||||
import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite';
|
||||
import * as Rooms from '../../Rooms';
|
||||
import linkifyMatrix from "../../linkify-matrix";
|
||||
import * as Lifecycle from '../../Lifecycle';
|
||||
|
@ -52,21 +51,22 @@ import { getHomePageUrl } from '../../utils/pages';
|
|||
import createRoom from "../../createRoom";
|
||||
import KeyRequestHandler from '../../KeyRequestHandler';
|
||||
import { _t, getCurrentLanguage } from '../../languageHandler';
|
||||
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
||||
import SettingsStore, { SettingLevel } from "../../settings/SettingsStore";
|
||||
import ThemeController from "../../settings/controllers/ThemeController";
|
||||
import { startAnyRegistrationFlow } from "../../Registration.js";
|
||||
import { messageForSyncError } from '../../utils/ErrorUtils';
|
||||
import ResizeNotifier from "../../utils/ResizeNotifier";
|
||||
import { ValidatedServerConfig } from "../../utils/AutoDiscoveryUtils";
|
||||
import AutoDiscoveryUtils from "../../utils/AutoDiscoveryUtils";
|
||||
import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../utils/AutoDiscoveryUtils";
|
||||
import DMRoomMap from '../../utils/DMRoomMap';
|
||||
import { countRoomsWithNotif } from '../../RoomNotifs';
|
||||
import { ThemeWatcher } from "../../theme";
|
||||
import { storeRoomAliasInCache } from '../../RoomAliasCache';
|
||||
import {defer, IDeferred} from "../../utils/promise";
|
||||
import { defer, IDeferred } from "../../utils/promise";
|
||||
import ToastStore from "../../stores/ToastStore";
|
||||
import * as StorageManager from "../../utils/StorageManager";
|
||||
import type LoggedInViewType from "./LoggedInView";
|
||||
import { ViewUserPayload } from "../../dispatcher/payloads/ViewUserPayload";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
|
||||
/** constants for MatrixChat.state.view */
|
||||
export enum Views {
|
||||
|
@ -1755,8 +1755,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
|
||||
const member = new RoomMember(null, userId);
|
||||
if (!member) { return; }
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
dis.dispatch<ViewUserPayload>({
|
||||
action: Action.ViewUser,
|
||||
member: member,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import SettingsStore from "../../settings/SettingsStore";
|
|||
import {RIGHT_PANEL_PHASES, RIGHT_PANEL_PHASES_NO_ARGS} from "../../stores/RightPanelStorePhases";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import {Action} from "../../dispatcher/actions";
|
||||
|
||||
export default class RightPanel extends React.Component {
|
||||
static get propTypes() {
|
||||
|
@ -237,7 +238,7 @@ export default class RightPanel extends React.Component {
|
|||
// within a room, so go back to the member panel if we were in the encryption panel,
|
||||
// or the member list if we were in the member panel... phew.
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: this.state.phase === RIGHT_PANEL_PHASES.EncryptionPanel ?
|
||||
this.state.member : null,
|
||||
});
|
||||
|
@ -266,7 +267,7 @@ export default class RightPanel extends React.Component {
|
|||
if (SettingsStore.getValue("feature_cross_signing")) {
|
||||
const onClose = () => {
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: null,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ import createReactClass from 'create-react-class';
|
|||
import * as Avatar from '../../../Avatar';
|
||||
import * as sdk from "../../../index";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'MemberAvatar',
|
||||
|
@ -33,7 +34,7 @@ export default createReactClass({
|
|||
resizeMethod: PropTypes.string,
|
||||
// The onClick to give the avatar
|
||||
onClick: PropTypes.func,
|
||||
// Whether the onClick of the avatar should be overriden to dispatch 'view_user'
|
||||
// Whether the onClick of the avatar should be overriden to dispatch `Action.ViewUser`
|
||||
viewUserOnClick: PropTypes.bool,
|
||||
title: PropTypes.string,
|
||||
},
|
||||
|
@ -85,7 +86,7 @@ export default createReactClass({
|
|||
if (viewUserOnClick) {
|
||||
onClick = () => {
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
action: Action.ViewUser,
|
||||
member: this.props.member,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -26,6 +26,7 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
|||
import FlairStore from "../../../stores/FlairStore";
|
||||
import {getPrimaryPermalinkEntity} from "../../../utils/permalinks/Permalinks";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
// For URLs of matrix.to links in the timeline which have been reformatted by
|
||||
// HttpUtils transformTags to relative links. This excludes event URLs (with `[^\/]*`)
|
||||
|
@ -191,7 +192,7 @@ const Pill = createReactClass({
|
|||
|
||||
onUserPillClicked: function() {
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
action: Action.ViewUser,
|
||||
member: this.state.member,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -28,6 +28,7 @@ import GroupStore from '../../../stores/GroupStore';
|
|||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'GroupMemberInfo',
|
||||
|
@ -103,7 +104,7 @@ export default createReactClass({
|
|||
).then(() => {
|
||||
// return to the user list
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: null,
|
||||
});
|
||||
}).catch((e) => {
|
||||
|
@ -124,7 +125,7 @@ export default createReactClass({
|
|||
_onCancel: function(e) {
|
||||
// Go back to the user list
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: null,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -23,6 +23,8 @@ import { _t } from '../../../languageHandler';
|
|||
import HeaderButton from './HeaderButton';
|
||||
import HeaderButtons, {HEADER_KIND_GROUP} from './HeaderButtons';
|
||||
import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
import {ActionPayload} from "../../../dispatcher/payloads";
|
||||
|
||||
const GROUP_PHASES = [
|
||||
RIGHT_PANEL_PHASES.GroupMemberInfo,
|
||||
|
@ -40,10 +42,10 @@ export default class GroupHeaderButtons extends HeaderButtons {
|
|||
this._onRoomsClicked = this._onRoomsClicked.bind(this);
|
||||
}
|
||||
|
||||
onAction(payload) {
|
||||
onAction(payload: ActionPayload) {
|
||||
super.onAction(payload);
|
||||
|
||||
if (payload.action === "view_user") {
|
||||
if (payload.action === Action.ViewUser) {
|
||||
if (payload.member) {
|
||||
this.setPhase(RIGHT_PANEL_PHASES.RoomMemberInfo, {member: payload.member});
|
||||
} else {
|
||||
|
|
|
@ -23,6 +23,8 @@ import { _t } from '../../../languageHandler';
|
|||
import HeaderButton from './HeaderButton';
|
||||
import HeaderButtons, {HEADER_KIND_ROOM} from './HeaderButtons';
|
||||
import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
import {ActionPayload} from "../../../dispatcher/payloads";
|
||||
|
||||
const MEMBER_PHASES = [
|
||||
RIGHT_PANEL_PHASES.RoomMemberList,
|
||||
|
@ -39,9 +41,9 @@ export default class RoomHeaderButtons extends HeaderButtons {
|
|||
this._onNotificationsClicked = this._onNotificationsClicked.bind(this);
|
||||
}
|
||||
|
||||
onAction(payload) {
|
||||
onAction(payload: ActionPayload) {
|
||||
super.onAction(payload);
|
||||
if (payload.action === "view_user") {
|
||||
if (payload.action === Action.ViewUser) {
|
||||
if (payload.member) {
|
||||
this.setPhase(RIGHT_PANEL_PHASES.RoomMemberInfo, {member: payload.member});
|
||||
} else {
|
||||
|
|
|
@ -44,6 +44,7 @@ import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases";
|
|||
import EncryptionPanel from "./EncryptionPanel";
|
||||
import { useAsyncMemo } from '../../../hooks/useAsyncMemo';
|
||||
import { verifyUser, legacyVerifyUser, verifyDevice } from '../../../verification';
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
const _disambiguateDevices = (devices) => {
|
||||
const names = Object.create(null);
|
||||
|
@ -841,7 +842,7 @@ const GroupAdminToolsSection = ({children, groupId, groupMember, startUpdating,
|
|||
cli.removeUserFromGroup(groupId, groupMember.userId).then(() => {
|
||||
// return to the user list
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: null,
|
||||
});
|
||||
}).catch((e) => {
|
||||
|
|
|
@ -48,6 +48,7 @@ import E2EIcon from "./E2EIcon";
|
|||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'MemberInfo',
|
||||
|
@ -724,7 +725,7 @@ export default createReactClass({
|
|||
|
||||
onCancel: function(e) {
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: null,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -23,6 +23,7 @@ import * as sdk from "../../../index";
|
|||
import dis from "../../../dispatcher/dispatcher";
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'MemberTile',
|
||||
|
@ -185,7 +186,7 @@ export default createReactClass({
|
|||
|
||||
onClick: function(e) {
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
action: Action.ViewUser,
|
||||
member: this.props.member,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -19,5 +19,19 @@ export type DispatcherAction = Action | string;
|
|||
|
||||
export enum Action {
|
||||
// TODO: Populate with actual actions
|
||||
// This is lazily generated as it also includes fixing a bunch of references. Work
|
||||
// that we don't really want to take on in a giant chunk. We should always define
|
||||
// new actions here, and ideally when we touch existing ones we take some time to
|
||||
// define them correctly.
|
||||
|
||||
// When defining a new action, please use lower_scored_case with an optional class
|
||||
// name prefix. For example, `RoomListStore.view_room` or `view_user_settings`.
|
||||
// New definitions should also receive an accompanying interface in the payloads
|
||||
// directory.
|
||||
|
||||
/**
|
||||
* View a user's profile. Should be used with a ViewUserPayload.
|
||||
*/
|
||||
ViewUser = "view_user",
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ export class MatrixDispatcher extends Dispatcher<ActionPayload> {
|
|||
* an operation that the browser requires user interaction
|
||||
* for. Default false (async).
|
||||
*/
|
||||
dispatch(payload: ActionPayload, sync = false) {
|
||||
dispatch<T extends ActionPayload>(payload: T, sync = false) {
|
||||
if (payload instanceof AsyncActionPayload) {
|
||||
payload.fn((action: ActionPayload) => {
|
||||
this.dispatch(action, sync);
|
||||
|
|
29
src/dispatcher/payloads/ViewUserPayload.ts
Normal file
29
src/dispatcher/payloads/ViewUserPayload.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
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 { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { ActionPayload } from "../payloads";
|
||||
import { Action } from "../actions";
|
||||
|
||||
export interface ViewUserPayload extends ActionPayload {
|
||||
action: Action.ViewUser,
|
||||
|
||||
/**
|
||||
* The member to view. May be null or falsy to indicate that no member
|
||||
* should be shown (hide whichever relevant components).
|
||||
*/
|
||||
member?: RoomMember;
|
||||
}
|
Loading…
Reference in a new issue