type Actions (#7862)
* type ViewHomPage action Signed-off-by: Kerry Archibald <kerrya@element.io> * type spacestore actions Signed-off-by: Kerry Archibald <kerrya@element.io> * lint Signed-off-by: Kerry Archibald <kerrya@element.io> * add action types Signed-off-by: Kerry Archibald <kerrya@element.io> * use new action types in stores Signed-off-by: Kerry Archibald <kerrya@element.io> * remove debug change Signed-off-by: Kerry Archibald <kerrya@element.io> * stricter keyboard shortcut types Signed-off-by: Kerry Archibald <kerrya@element.io> * action comments Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
parent
57595bc593
commit
5b8d440406
33 changed files with 304 additions and 73 deletions
|
@ -26,6 +26,7 @@ import dis from './dispatcher/dispatcher';
|
|||
import Modal from './Modal';
|
||||
import { _t } from './languageHandler';
|
||||
import QuestionDialog from "./components/views/dialogs/QuestionDialog";
|
||||
import { Action } from "./dispatcher/actions";
|
||||
|
||||
// Regex for what a "safe" or "Matrix-looking" localpart would be.
|
||||
// TODO: Update as needed for https://github.com/matrix-org/matrix-doc/issues/1514
|
||||
|
@ -69,7 +70,7 @@ export async function startAnyRegistrationFlow(
|
|||
if (proceed) {
|
||||
dis.dispatch({ action: 'start_registration', screenAfterLogin: options.screen_after });
|
||||
} else if (options.go_home_on_cancel) {
|
||||
dis.dispatch({ action: 'view_home_page' });
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
} else if (options.go_welcome_on_cancel) {
|
||||
dis.dispatch({ action: 'view_welcome_page' });
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
|
||||
import { _td } from "../languageHandler";
|
||||
import { isMac, Key } from "../Keyboard";
|
||||
import { ISetting } from "../settings/Settings";
|
||||
import { IBaseSetting } from "../settings/Settings";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import IncompatibleController from "../settings/controllers/IncompatibleController";
|
||||
|
||||
|
@ -119,9 +119,20 @@ export enum KeyBindingAction {
|
|||
ToggleHiddenEventVisibility = 'KeyBinding.toggleHiddenEventVisibility',
|
||||
}
|
||||
|
||||
export type KeyBindingConfig = {
|
||||
key: string;
|
||||
ctrlOrCmdKey?: boolean;
|
||||
ctrlKey?: boolean;
|
||||
altKey?: boolean;
|
||||
shiftKey?: boolean;
|
||||
metaKey?: boolean;
|
||||
};
|
||||
|
||||
type KeyboardShortcutSetting = IBaseSetting<KeyBindingConfig>;
|
||||
|
||||
type IKeyboardShortcuts = {
|
||||
// TODO: We should figure out what to do with the keyboard shortcuts that are not handled by KeybindingManager
|
||||
[k in (KeyBindingAction | string)]: ISetting;
|
||||
[k in (KeyBindingAction | string)]: KeyboardShortcutSetting;
|
||||
};
|
||||
|
||||
export interface ICategory {
|
||||
|
@ -614,7 +625,11 @@ export const getKeyboardShortcuts = (): IKeyboardShortcuts => {
|
|||
}, {});
|
||||
};
|
||||
|
||||
export const registerShortcut = (shortcutName: string, categoryName: CategoryName, shortcut: ISetting): void => {
|
||||
export const registerShortcut = (
|
||||
shortcutName: string,
|
||||
categoryName: CategoryName,
|
||||
shortcut: KeyboardShortcutSetting,
|
||||
): void => {
|
||||
KEYBOARD_SHORTCUTS[shortcutName] = shortcut;
|
||||
CATEGORIES[categoryName].settingNames.push(shortcutName);
|
||||
};
|
||||
|
|
|
@ -342,7 +342,7 @@ class FeaturedUser extends React.Component {
|
|||
e.stopPropagation();
|
||||
|
||||
dis.dispatch({
|
||||
action: 'view_start_chat_or_reuse',
|
||||
action: Action.ViewStartChatOrReuse,
|
||||
user_id: this.props.summaryInfo.user_id,
|
||||
});
|
||||
};
|
||||
|
@ -491,7 +491,7 @@ export default class GroupView extends React.Component {
|
|||
if (this._unmounted || groupId !== errorGroupId) return;
|
||||
if (err.errcode === 'M_GUEST_ACCESS_FORBIDDEN' && !willDoOnboarding) {
|
||||
dis.dispatch({
|
||||
action: 'do_after_sync_prepared',
|
||||
action: Action.DoAfterSyncPrepared,
|
||||
deferred_action: {
|
||||
action: 'view_group',
|
||||
group_id: groupId,
|
||||
|
|
|
@ -490,7 +490,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
break;
|
||||
case KeyBindingAction.GoToHome:
|
||||
dis.dispatch({
|
||||
action: 'view_home_page',
|
||||
action: Action.ViewHomePage,
|
||||
});
|
||||
Modal.closeCurrentModal("homeKeyboardShortcut");
|
||||
handled = true;
|
||||
|
|
|
@ -119,6 +119,10 @@ import { SummarizedNotificationState } from "../../stores/notifications/Summariz
|
|||
import GenericToast from '../views/toasts/GenericToast';
|
||||
import Views from '../../Views';
|
||||
import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { ViewHomePagePayload } from '../../dispatcher/payloads/ViewHomePagePayload';
|
||||
import { AfterLeaveRoomPayload } from '../../dispatcher/payloads/AfterLeaveRoomPayload';
|
||||
import { DoAfterSyncPreparedPayload } from '../../dispatcher/payloads/DoAfterSyncPreparedPayload';
|
||||
import { ViewStartChatOrReusePayload } from '../../dispatcher/payloads/ViewStartChatOrReusePayload';
|
||||
|
||||
// legacy export
|
||||
export { default as Views } from "../../Views";
|
||||
|
@ -541,7 +545,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
// will cause a full login and sync and finally the deferred
|
||||
// action will be dispatched.
|
||||
dis.dispatch({
|
||||
action: 'do_after_sync_prepared',
|
||||
action: Action.DoAfterSyncPrepared,
|
||||
deferred_action: payload,
|
||||
});
|
||||
dis.dispatch({ action: 'require_registration' });
|
||||
|
@ -632,7 +636,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
MatrixClientPeg.get().leave(payload.room_id).then(() => {
|
||||
modal.close();
|
||||
if (this.state.currentRoomId === payload.room_id) {
|
||||
dis.dispatch({ action: 'view_home_page' });
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
}
|
||||
}, (err) => {
|
||||
modal.close();
|
||||
|
@ -705,10 +709,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
case 'view_welcome_page':
|
||||
this.viewWelcome();
|
||||
break;
|
||||
case 'view_home_page':
|
||||
case Action.ViewHomePage:
|
||||
this.viewHome(payload.justRegistered);
|
||||
break;
|
||||
case 'view_start_chat_or_reuse':
|
||||
case Action.ViewStartChatOrReuse:
|
||||
this.chatCreateOrReuse(payload.user_id);
|
||||
break;
|
||||
case 'view_create_chat':
|
||||
|
@ -1057,10 +1061,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
// No point in making 2 DMs with welcome bot. This assumes view_set_mxid will
|
||||
// result in a new DM with the welcome user.
|
||||
if (userId !== this.props.config.welcomeUserId) {
|
||||
dis.dispatch({
|
||||
action: 'do_after_sync_prepared',
|
||||
dis.dispatch<DoAfterSyncPreparedPayload<ViewStartChatOrReusePayload>>({
|
||||
action: Action.DoAfterSyncPrepared,
|
||||
deferred_action: {
|
||||
action: 'view_start_chat_or_reuse',
|
||||
action: Action.ViewStartChatOrReuse,
|
||||
user_id: userId,
|
||||
},
|
||||
});
|
||||
|
@ -1162,8 +1166,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
if (shouldLeave) {
|
||||
leaveRoomBehaviour(roomId);
|
||||
|
||||
dis.dispatch({
|
||||
action: "after_leave_room",
|
||||
dis.dispatch<AfterLeaveRoomPayload>({
|
||||
action: Action.AfterLeaveRoom,
|
||||
room_id: roomId,
|
||||
});
|
||||
}
|
||||
|
@ -1176,7 +1180,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
MatrixClientPeg.get().forget(roomId).then(() => {
|
||||
// Switch to home page if we're currently viewing the forgotten room
|
||||
if (this.state.currentRoomId === roomId) {
|
||||
dis.dispatch({ action: "view_home_page" });
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
}
|
||||
|
||||
// We have to manually update the room list because the forgotten room will not
|
||||
|
@ -1275,7 +1279,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
if (welcomeUserRoom === null) {
|
||||
// We didn't redirect to the welcome user room, so show
|
||||
// the homepage.
|
||||
dis.dispatch({ action: 'view_home_page', justRegistered: true });
|
||||
dis.dispatch<ViewHomePagePayload>({ action: Action.ViewHomePage, justRegistered: true });
|
||||
}
|
||||
} else if (ThreepidInviteStore.instance.pickBestInvite()) {
|
||||
// The user has a 3pid invite pending - show them that
|
||||
|
@ -1288,7 +1292,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
} else {
|
||||
// The user has just logged in after registering,
|
||||
// so show the homepage.
|
||||
dis.dispatch({ action: 'view_home_page', justRegistered: true });
|
||||
dis.dispatch<ViewHomePagePayload>({ action: Action.ViewHomePage, justRegistered: true });
|
||||
}
|
||||
} else {
|
||||
this.showScreenAfterLogin();
|
||||
|
@ -1353,7 +1357,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
if (MatrixClientPeg.get().isGuest()) {
|
||||
dis.dispatch({ action: 'view_welcome_page' });
|
||||
} else {
|
||||
dis.dispatch({ action: 'view_home_page' });
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1666,7 +1670,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
const isLoggedOutOrGuest = !cli || cli.isGuest();
|
||||
if (!isLoggedOutOrGuest && AUTH_SCREENS.includes(screen)) {
|
||||
// user is logged in and landing on an auth page which will uproot their session, redirect them home instead
|
||||
dis.dispatch({ action: "view_home_page" });
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1714,7 +1718,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
} else if (screen === 'home') {
|
||||
dis.dispatch({
|
||||
action: 'view_home_page',
|
||||
action: Action.ViewHomePage,
|
||||
});
|
||||
} else if (screen === 'start') {
|
||||
this.showScreen('home');
|
||||
|
@ -1737,7 +1741,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
PlatformPeg.get().startSingleSignOn(cli, type, this.getFragmentAfterLogin());
|
||||
} else if (screen === 'groups') {
|
||||
if (SpaceStore.spacesEnabled) {
|
||||
dis.dispatch({ action: "view_home_page" });
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
return;
|
||||
}
|
||||
dis.dispatch({
|
||||
|
|
|
@ -47,6 +47,7 @@ import { E2EStatus } from '../../utils/ShieldUtils';
|
|||
import TimelineCard from '../views/right_panel/TimelineCard';
|
||||
import { UPDATE_EVENT } from '../../stores/AsyncStore';
|
||||
import { IRightPanelCard, IRightPanelCardState } from '../../stores/right-panel/RightPanelStoreIPanelState';
|
||||
import { Action } from '../../dispatcher/actions';
|
||||
|
||||
interface IProps {
|
||||
room?: Room; // if showing panels for a given room, this is set
|
||||
|
@ -134,7 +135,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
// to the home page which is not obviously the correct thing to do, but I'm not sure
|
||||
// anything else is - we could hide the close button altogether?)
|
||||
dis.dispatch({
|
||||
action: "view_home_page",
|
||||
action: Action.ViewHomePage,
|
||||
});
|
||||
} else if (
|
||||
this.state.phase === RightPanelPhases.EncryptionPanel &&
|
||||
|
|
|
@ -103,6 +103,7 @@ import { ActionPayload } from "../../dispatcher/payloads";
|
|||
import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts";
|
||||
import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { JoinRoomPayload } from "../../dispatcher/payloads/JoinRoomPayload";
|
||||
import { DoAfterSyncPreparedPayload } from '../../dispatcher/payloads/DoAfterSyncPreparedPayload';
|
||||
|
||||
const DEBUG = false;
|
||||
let debuglog = function(msg: string) {};
|
||||
|
@ -1273,11 +1274,12 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
if (this.context && this.context.isGuest()) {
|
||||
// Join this room once the user has registered and logged in
|
||||
// (If we failed to peek, we may not have a valid room object.)
|
||||
dis.dispatch({
|
||||
action: 'do_after_sync_prepared',
|
||||
dis.dispatch<DoAfterSyncPreparedPayload<ViewRoomPayload>>({
|
||||
action: Action.DoAfterSyncPrepared,
|
||||
deferred_action: {
|
||||
action: Action.ViewRoom,
|
||||
room_id: this.getRoomId(),
|
||||
metricsTrigger: undefined,
|
||||
},
|
||||
});
|
||||
dis.dispatch({ action: 'require_registration' });
|
||||
|
@ -1568,7 +1570,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
rejecting: true,
|
||||
});
|
||||
this.context.leave(this.state.roomId).then(() => {
|
||||
dis.dispatch({ action: 'view_home_page' });
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
this.setState({
|
||||
rejecting: false,
|
||||
});
|
||||
|
@ -1601,7 +1603,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
await this.context.setIgnoredUsers(ignoredUsers);
|
||||
|
||||
await this.context.leave(this.state.roomId);
|
||||
dis.dispatch({ action: 'view_home_page' });
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
this.setState({
|
||||
rejecting: false,
|
||||
});
|
||||
|
|
|
@ -61,6 +61,7 @@ import MatrixClientContext from "../../contexts/MatrixClientContext";
|
|||
import { SettingUpdatedPayload } from "../../dispatcher/payloads/SettingUpdatedPayload";
|
||||
import UserIdentifierCustomisations from "../../customisations/UserIdentifier";
|
||||
import PosthogTrackers from "../../PosthogTrackers";
|
||||
import { ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePayload";
|
||||
|
||||
const CustomStatusSection = () => {
|
||||
const cli = useContext(MatrixClientContext);
|
||||
|
@ -360,7 +361,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
defaultDispatcher.dispatch({ action: 'view_home_page' });
|
||||
defaultDispatcher.dispatch<ViewHomePagePayload>({ action: Action.ViewHomePage });
|
||||
this.setState({ contextMenuPosition: null }); // also close the menu
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import SettingsStore from "../../../settings/SettingsStore";
|
|||
import { UIFeature } from "../../../settings/UIFeature";
|
||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import { Action } from '../../../dispatcher/actions';
|
||||
|
||||
export const ROOM_GENERAL_TAB = "ROOM_GENERAL_TAB";
|
||||
export const ROOM_SECURITY_TAB = "ROOM_SECURITY_TAB";
|
||||
|
@ -75,7 +76,7 @@ export default class RoomSettingsDialog extends React.Component<IProps, IState>
|
|||
private onAction = (payload): void => {
|
||||
// When view changes below us, close the room settings
|
||||
// whilst the modal is open this can only be triggered when someone hits Leave Room
|
||||
if (payload.action === 'view_home_page') {
|
||||
if (payload.action === Action.ViewHomePage) {
|
||||
this.props.onFinished(true);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -30,6 +30,7 @@ import SettingsStore from "../../../settings/SettingsStore";
|
|||
import { UIFeature } from "../../../settings/UIFeature";
|
||||
import AdvancedRoomSettingsTab from "../settings/tabs/room/AdvancedRoomSettingsTab";
|
||||
import RolesRoomSettingsTab from "../settings/tabs/room/RolesRoomSettingsTab";
|
||||
import { Action } from '../../../dispatcher/actions';
|
||||
|
||||
export enum SpaceSettingsTab {
|
||||
General = "SPACE_GENERAL_TAB",
|
||||
|
@ -44,8 +45,8 @@ interface IProps extends IDialogProps {
|
|||
}
|
||||
|
||||
const SpaceSettingsDialog: React.FC<IProps> = ({ matrixClient: cli, space, onFinished }) => {
|
||||
useDispatcher(defaultDispatcher, ({ action, ...params }) => {
|
||||
if (action === "after_leave_room" && params.room_id === space.roomId) {
|
||||
useDispatcher(defaultDispatcher, (payload) => {
|
||||
if (payload.action === Action.AfterLeaveRoom && payload.room_id === space.roomId) {
|
||||
onFinished(false);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -49,6 +49,7 @@ import RoomViewStore from '../../../stores/RoomViewStore';
|
|||
import WidgetUtils from '../../../utils/WidgetUtils';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import { ActionPayload } from "../../../dispatcher/payloads";
|
||||
import { Action } from '../../../dispatcher/actions';
|
||||
|
||||
interface IProps {
|
||||
app: IApp;
|
||||
|
@ -447,7 +448,7 @@ export default class AppTile extends React.Component<IProps, IState> {
|
|||
}
|
||||
break;
|
||||
|
||||
case "after_leave_room":
|
||||
case Action.AfterLeaveRoom:
|
||||
if (payload.room_id === this.props.room?.roomId) {
|
||||
// call this before we get it echoed down /sync, so it doesn't hang around as long and look jarring
|
||||
this.onUserLeftRoom();
|
||||
|
|
|
@ -24,13 +24,14 @@ import {
|
|||
ICategory,
|
||||
CATEGORIES,
|
||||
CategoryName,
|
||||
KeyBindingConfig,
|
||||
} from "../../../../../accessibility/KeyboardShortcuts";
|
||||
import SdkConfig from "../../../../../SdkConfig";
|
||||
import { isMac, Key } from "../../../../../Keyboard";
|
||||
import { _t } from "../../../../../languageHandler";
|
||||
|
||||
// TODO: This should return KeyCombo but it has ctrlOrCmd instead of ctrlOrCmdKey
|
||||
const getKeyboardShortcutValue = (name: string) => {
|
||||
const getKeyboardShortcutValue = (name: string): KeyBindingConfig => {
|
||||
return getKeyboardShortcuts()[name]?.default;
|
||||
};
|
||||
|
||||
|
|
|
@ -45,6 +45,16 @@ export enum Action {
|
|||
*/
|
||||
ViewRoomDirectory = "view_room_directory",
|
||||
|
||||
/**
|
||||
* Fires when viewing room by room_alias fails to find room
|
||||
*/
|
||||
ViewRoomError = "view_room_error",
|
||||
|
||||
/**
|
||||
* Navigates to app home
|
||||
*/
|
||||
ViewHomePage = "view_home_page",
|
||||
|
||||
/**
|
||||
* Forces the theme to reload. No additional payload information required.
|
||||
*/
|
||||
|
@ -224,4 +234,20 @@ export enum Action {
|
|||
* Used to trigger auto rageshakes when configured
|
||||
*/
|
||||
ReportKeyBackupNotEnabled = "report_key_backup_not_enabled",
|
||||
|
||||
/**
|
||||
* Dispatched after leave room or space is finished
|
||||
*/
|
||||
AfterLeaveRoom = "after_leave_room",
|
||||
|
||||
/**
|
||||
* Used to defer actions until after sync is complete
|
||||
* LifecycleStore will emit deferredAction payload after 'MatrixActions.sync'
|
||||
*/
|
||||
DoAfterSyncPrepared = "do_after_sync_prepared",
|
||||
|
||||
/**
|
||||
* Fired when clicking user name from group view
|
||||
*/
|
||||
ViewStartChatOrReuse = "view_start_chat_or_reuse",
|
||||
}
|
||||
|
|
26
src/dispatcher/payloads/AfterLeaveRoomPayload.ts
Normal file
26
src/dispatcher/payloads/AfterLeaveRoomPayload.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
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 { Room } from "matrix-js-sdk";
|
||||
|
||||
import { Action } from "../actions";
|
||||
import { ActionPayload } from "../payloads";
|
||||
|
||||
export interface AfterLeaveRoomPayload extends ActionPayload {
|
||||
action: Action.AfterLeaveRoom;
|
||||
// eslint-disable-next-line camelcase
|
||||
room_id?: Room["roomId"];
|
||||
}
|
24
src/dispatcher/payloads/DoAfterSyncPreparedPayload.ts
Normal file
24
src/dispatcher/payloads/DoAfterSyncPreparedPayload.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
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 { ActionPayload } from "../payloads";
|
||||
import { Action } from "../actions";
|
||||
|
||||
export interface DoAfterSyncPreparedPayload<T extends ActionPayload> extends Pick<ActionPayload, "action"> {
|
||||
action: Action.DoAfterSyncPrepared;
|
||||
// eslint-disable-next-line camelcase
|
||||
deferred_action: T;
|
||||
}
|
27
src/dispatcher/payloads/JoinRoomErrorPayload.ts
Normal file
27
src/dispatcher/payloads/JoinRoomErrorPayload.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
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 { MatrixError } from "matrix-js-sdk";
|
||||
|
||||
import { ActionPayload } from "../payloads";
|
||||
import { Action } from "../actions";
|
||||
|
||||
export interface JoinRoomErrorPayload extends Pick<ActionPayload, "action"> {
|
||||
action: Action.JoinRoomError;
|
||||
|
||||
roomId: string;
|
||||
err?: MatrixError;
|
||||
}
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
import { ActionPayload } from "../payloads";
|
||||
import { Action } from "../actions";
|
||||
import { SettingLevel } from "../../settings/SettingLevel";
|
||||
import { SettingValueType } from "../../settings/Settings";
|
||||
|
||||
export interface SettingUpdatedPayload extends ActionPayload {
|
||||
action: Action.SettingUpdated;
|
||||
|
@ -25,5 +26,5 @@ export interface SettingUpdatedPayload extends ActionPayload {
|
|||
roomId: string;
|
||||
level: SettingLevel;
|
||||
newValueAtLevel: SettingLevel;
|
||||
newValue: any;
|
||||
newValue: SettingValueType;
|
||||
}
|
||||
|
|
25
src/dispatcher/payloads/ViewHomePagePayload.ts
Normal file
25
src/dispatcher/payloads/ViewHomePagePayload.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
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 { Action } from "../actions";
|
||||
import { ActionPayload } from "../payloads";
|
||||
|
||||
export interface ViewHomePagePayload extends ActionPayload {
|
||||
action: Action.ViewHomePage;
|
||||
// eslint-disable-next-line camelcase
|
||||
context_switch?: boolean;
|
||||
justRegistered?: boolean;
|
||||
}
|
29
src/dispatcher/payloads/ViewRoomErrorPayload.ts
Normal file
29
src/dispatcher/payloads/ViewRoomErrorPayload.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
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 { MatrixError, Room } from "matrix-js-sdk";
|
||||
|
||||
import { ActionPayload } from "../payloads";
|
||||
import { Action } from "../actions";
|
||||
|
||||
export interface ViewRoomErrorPayload extends Pick<ActionPayload, "action"> {
|
||||
action: Action.ViewRoomError;
|
||||
// eslint-disable-next-line camelcase
|
||||
room_id: Room["roomId"];
|
||||
// eslint-disable-next-line camelcase
|
||||
room_alias?: string;
|
||||
err?: MatrixError;
|
||||
}
|
26
src/dispatcher/payloads/ViewStartChatOrReusePayload.ts
Normal file
26
src/dispatcher/payloads/ViewStartChatOrReusePayload.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
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 { User } from "matrix-js-sdk";
|
||||
|
||||
import { ActionPayload } from "../payloads";
|
||||
import { Action } from "../actions";
|
||||
|
||||
export interface ViewStartChatOrReusePayload extends Pick<ActionPayload, "action"> {
|
||||
action: Action.ViewStartChatOrReuse;
|
||||
// eslint-disable-next-line camelcase
|
||||
user_id: User["userId"];
|
||||
}
|
|
@ -25,6 +25,8 @@ import { _t } from "../languageHandler";
|
|||
import dis from "../dispatcher/dispatcher";
|
||||
import { SettingLevel } from "../settings/SettingLevel";
|
||||
import { ActionPayload } from "../dispatcher/payloads";
|
||||
import { DoAfterSyncPreparedPayload } from "../dispatcher/payloads/DoAfterSyncPreparedPayload";
|
||||
import { Action } from "../dispatcher/actions";
|
||||
|
||||
// TODO: Move this and related files to the js-sdk or something once finalized.
|
||||
|
||||
|
@ -48,8 +50,8 @@ export class Mjolnir {
|
|||
this.mjolnirWatchRef = SettingsStore.watchSetting("mjolnirRooms", null, this.onListsChanged.bind(this));
|
||||
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
dis.dispatch({
|
||||
action: 'do_after_sync_prepared',
|
||||
dis.dispatch<DoAfterSyncPreparedPayload<ActionPayload>>({
|
||||
action: Action.DoAfterSyncPrepared,
|
||||
deferred_action: { action: 'setup_mjolnir' },
|
||||
});
|
||||
}
|
||||
|
|
|
@ -114,7 +114,14 @@ export const labGroupNames: Record<LabGroup, string> = {
|
|||
[LabGroup.Developer]: _td("Developer"),
|
||||
};
|
||||
|
||||
interface IBaseSetting {
|
||||
export type SettingValueType = boolean |
|
||||
number |
|
||||
string |
|
||||
number[] |
|
||||
string[] |
|
||||
Record<string, unknown>;
|
||||
|
||||
export interface IBaseSetting<T extends SettingValueType = SettingValueType> {
|
||||
isFeature?: false | undefined;
|
||||
|
||||
// Display names are strongly recommended for clarity.
|
||||
|
@ -134,7 +141,7 @@ interface IBaseSetting {
|
|||
// Required. Can be any data type. The value specified here should match
|
||||
// the data being stored (ie: if a boolean is used, the setting should
|
||||
// represent a boolean).
|
||||
default: any;
|
||||
default: T;
|
||||
|
||||
// Optional settings controller. See SettingsController for more information.
|
||||
controller?: SettingController;
|
||||
|
@ -166,7 +173,7 @@ interface IBaseSetting {
|
|||
};
|
||||
}
|
||||
|
||||
export interface IFeature extends Omit<IBaseSetting, "isFeature"> {
|
||||
export interface IFeature extends Omit<IBaseSetting<boolean>, "isFeature"> {
|
||||
// Must be set to true for features.
|
||||
isFeature: true;
|
||||
labsGroup: LabGroup;
|
||||
|
|
|
@ -18,13 +18,13 @@ import { Room } from "matrix-js-sdk/src/models/room";
|
|||
import { isNullOrUndefined } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import { ActionPayload } from "../dispatcher/payloads";
|
||||
import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
|
||||
import defaultDispatcher from "../dispatcher/dispatcher";
|
||||
import { arrayHasDiff } from "../utils/arrays";
|
||||
import { SettingLevel } from "../settings/SettingLevel";
|
||||
import { Action } from "../dispatcher/actions";
|
||||
import { SettingUpdatedPayload } from "../dispatcher/payloads/SettingUpdatedPayload";
|
||||
import { ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload";
|
||||
|
||||
const MAX_ROOMS = 20; // arbitrary
|
||||
const AUTOJOIN_WAIT_THRESHOLD_MS = 90000; // 90s, the time we wait for an autojoined room to show up
|
||||
|
@ -64,15 +64,14 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> {
|
|||
return this.matrixClient?.getVisibleRooms().length >= 20;
|
||||
}
|
||||
|
||||
protected async onAction(payload: ActionPayload) {
|
||||
protected async onAction(payload: SettingUpdatedPayload | ViewRoomPayload) {
|
||||
if (!this.matrixClient) return;
|
||||
|
||||
if (payload.action === Action.SettingUpdated) {
|
||||
const settingUpdatedPayload = payload as SettingUpdatedPayload;
|
||||
if (settingUpdatedPayload.settingName === 'breadcrumb_rooms') {
|
||||
if (payload.settingName === 'breadcrumb_rooms') {
|
||||
await this.updateRooms();
|
||||
} else if (settingUpdatedPayload.settingName === 'breadcrumbs' ||
|
||||
settingUpdatedPayload.settingName === 'feature_breadcrumbs_v2'
|
||||
} else if (payload.settingName === 'breadcrumbs' ||
|
||||
payload.settingName === 'feature_breadcrumbs_v2'
|
||||
) {
|
||||
await this.updateState({ enabled: SettingsStore.getValue("breadcrumbs", null) });
|
||||
}
|
||||
|
|
|
@ -16,8 +16,10 @@ limitations under the License.
|
|||
|
||||
import { Store } from 'flux/utils';
|
||||
|
||||
import { Action } from '../dispatcher/actions';
|
||||
import dis from '../dispatcher/dispatcher';
|
||||
import { ActionPayload } from "../dispatcher/payloads";
|
||||
import { DoAfterSyncPreparedPayload } from '../dispatcher/payloads/DoAfterSyncPreparedPayload';
|
||||
|
||||
interface IState {
|
||||
deferredAction: any;
|
||||
|
@ -44,9 +46,9 @@ class LifecycleStore extends Store<ActionPayload> {
|
|||
this.__emitChange();
|
||||
}
|
||||
|
||||
protected __onDispatch(payload: ActionPayload) { // eslint-disable-line @typescript-eslint/naming-convention
|
||||
protected __onDispatch(payload: ActionPayload | DoAfterSyncPreparedPayload<ActionPayload>) { // eslint-disable-line @typescript-eslint/naming-convention
|
||||
switch (payload.action) {
|
||||
case 'do_after_sync_prepared':
|
||||
case Action.DoAfterSyncPrepared:
|
||||
this.setState({
|
||||
deferredAction: payload.deferred_action,
|
||||
});
|
||||
|
|
|
@ -42,6 +42,8 @@ import SpaceStore from "./spaces/SpaceStore";
|
|||
import { isMetaSpace, MetaSpace } from "./spaces";
|
||||
import { JoinRoomPayload } from "../dispatcher/payloads/JoinRoomPayload";
|
||||
import { JoinRoomReadyPayload } from "../dispatcher/payloads/JoinRoomReadyPayload";
|
||||
import { JoinRoomErrorPayload } from "../dispatcher/payloads/JoinRoomErrorPayload";
|
||||
import { ViewRoomErrorPayload } from "../dispatcher/payloads/ViewRoomErrorPayload";
|
||||
|
||||
const NUM_JOIN_RETRY = 5;
|
||||
|
||||
|
@ -122,7 +124,7 @@ class RoomViewStore extends Store<ActionPayload> {
|
|||
// for these events blank out the roomId as we are no longer in the RoomView
|
||||
case 'view_create_group':
|
||||
case 'view_welcome_page':
|
||||
case 'view_home_page':
|
||||
case Action.ViewHomePage:
|
||||
case 'view_my_groups':
|
||||
case 'view_group':
|
||||
this.setState({
|
||||
|
@ -132,7 +134,7 @@ class RoomViewStore extends Store<ActionPayload> {
|
|||
wasContextSwitch: false,
|
||||
});
|
||||
break;
|
||||
case 'view_room_error':
|
||||
case Action.ViewRoomError:
|
||||
this.viewRoomError(payload);
|
||||
break;
|
||||
case 'will_join':
|
||||
|
@ -306,8 +308,8 @@ class RoomViewStore extends Store<ActionPayload> {
|
|||
roomId = result.room_id;
|
||||
} catch (err) {
|
||||
logger.error("RVS failed to get room id for alias: ", err);
|
||||
dis.dispatch({
|
||||
action: 'view_room_error',
|
||||
dis.dispatch<ViewRoomErrorPayload>({
|
||||
action: Action.ViewRoomError,
|
||||
room_id: null,
|
||||
room_alias: payload.room_alias,
|
||||
err,
|
||||
|
@ -324,7 +326,7 @@ class RoomViewStore extends Store<ActionPayload> {
|
|||
}
|
||||
}
|
||||
|
||||
private viewRoomError(payload: ActionPayload) {
|
||||
private viewRoomError(payload: ViewRoomErrorPayload) {
|
||||
this.setState({
|
||||
roomId: payload.room_id,
|
||||
roomAlias: payload.room_alias,
|
||||
|
@ -411,7 +413,7 @@ class RoomViewStore extends Store<ActionPayload> {
|
|||
});
|
||||
}
|
||||
|
||||
private joinRoomError(payload: ActionPayload) {
|
||||
private joinRoomError(payload: JoinRoomErrorPayload) {
|
||||
this.setState({
|
||||
joining: false,
|
||||
joinError: payload.err,
|
||||
|
|
|
@ -98,8 +98,6 @@ export class EchoStore extends AsyncStoreWithClient<IState> {
|
|||
}
|
||||
}
|
||||
|
||||
protected async onAction(payload: ActionPayload): Promise<any> {
|
||||
// We have nothing to actually listen for
|
||||
return Promise.resolve();
|
||||
protected async onAction(payload: ActionPayload): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,7 +140,6 @@ export class RoomNotificationStateStore extends AsyncStoreWithClient<IState> {
|
|||
}
|
||||
|
||||
// We don't need this, but our contract says we do.
|
||||
protected async onAction(payload: ActionPayload) {
|
||||
return Promise.resolve();
|
||||
protected async onAction(payload: ActionPayload): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,8 +67,7 @@ export default class RoomListLayoutStore extends AsyncStoreWithClient<IState> {
|
|||
}
|
||||
|
||||
// We don't need this function, but our contract says we do
|
||||
protected async onAction(payload: ActionPayload): Promise<any> {
|
||||
return Promise.resolve();
|
||||
protected async onAction(payload: ActionPayload): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
|||
|
||||
import { AsyncStoreWithClient } from "../AsyncStoreWithClient";
|
||||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
||||
import { ActionPayload } from "../../dispatcher/payloads";
|
||||
import RoomListStore from "../room-list/RoomListStore";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import DMRoomMap from "../../utils/DMRoomMap";
|
||||
|
@ -61,6 +60,9 @@ import {
|
|||
} from "./flattenSpaceHierarchy";
|
||||
import { PosthogAnalytics } from "../../PosthogAnalytics";
|
||||
import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePayload";
|
||||
import { SwitchSpacePayload } from "../../dispatcher/payloads/SwitchSpacePayload";
|
||||
import { AfterLeaveRoomPayload } from "../../dispatcher/payloads/AfterLeaveRoomPayload";
|
||||
|
||||
interface IState { }
|
||||
|
||||
|
@ -92,7 +94,7 @@ const validOrder = (order: string): string | undefined => {
|
|||
};
|
||||
|
||||
// For sorting space children using a validated `order`, `origin_server_ts`, `room_id`
|
||||
export const getChildOrder = (order: string, ts: number, roomId: string): Array<Many<ListIteratee<any>>> => {
|
||||
export const getChildOrder = (order: string, ts: number, roomId: string): Array<Many<ListIteratee<unknown>>> => {
|
||||
return [validOrder(order) ?? NaN, ts, roomId]; // NaN has lodash sort it at the end in asc
|
||||
};
|
||||
|
||||
|
@ -100,6 +102,13 @@ const getRoomFn: FetchRoomFn = (room: Room) => {
|
|||
return RoomNotificationStateStore.instance.getRoomState(room);
|
||||
};
|
||||
|
||||
type SpaceStoreActions =
|
||||
| SettingUpdatedPayload
|
||||
| ViewRoomPayload
|
||||
| ViewHomePagePayload
|
||||
| SwitchSpacePayload
|
||||
| AfterLeaveRoomPayload;
|
||||
|
||||
export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||
// The spaces representing the roots of the various tree-like hierarchies
|
||||
private rootSpaces: Room[] = [];
|
||||
|
@ -254,8 +263,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
metricsTrigger: "WebSpaceContextSwitch",
|
||||
});
|
||||
} else {
|
||||
defaultDispatcher.dispatch({
|
||||
action: "view_home_page",
|
||||
defaultDispatcher.dispatch<ViewHomePagePayload>({
|
||||
action: Action.ViewHomePage,
|
||||
context_switch: true,
|
||||
});
|
||||
}
|
||||
|
@ -1097,7 +1106,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
this.setActiveSpace(this.enabledMetaSpaces[0] ?? this.spacePanelSpaces[0]?.roomId, contextSwitch);
|
||||
}
|
||||
|
||||
protected async onAction(payload: ActionPayload) {
|
||||
protected async onAction(payload: SpaceStoreActions) {
|
||||
if (!spacesEnabled || !this.matrixClient) return;
|
||||
|
||||
switch (payload.action) {
|
||||
|
@ -1129,14 +1138,14 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
break;
|
||||
}
|
||||
|
||||
case "view_home_page":
|
||||
case Action.ViewHomePage:
|
||||
if (!payload.context_switch && this.enabledMetaSpaces.includes(MetaSpace.Home)) {
|
||||
this.setActiveSpace(MetaSpace.Home, false);
|
||||
window.localStorage.setItem(getSpaceContextKey(this.activeSpace), "");
|
||||
}
|
||||
break;
|
||||
|
||||
case "after_leave_room":
|
||||
case Action.AfterLeaveRoom:
|
||||
if (!isMetaSpace(this._activeSpace) && payload.room_id === this._activeSpace) {
|
||||
// User has left the current space, go to first space
|
||||
this.goToFirstSpace(true);
|
||||
|
|
|
@ -40,7 +40,7 @@ export class WidgetMessagingStore extends AsyncStoreWithClient<unknown> {
|
|||
return WidgetMessagingStore.internalInstance;
|
||||
}
|
||||
|
||||
protected async onAction(payload: ActionPayload): Promise<any> {
|
||||
protected async onAction(payload: ActionPayload): Promise<void> {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import { isMetaSpace } from "../stores/spaces";
|
|||
import SpaceStore from "../stores/spaces/SpaceStore";
|
||||
import { Action } from "../dispatcher/actions";
|
||||
import { ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload";
|
||||
import { ViewHomePagePayload } from "../dispatcher/payloads/ViewHomePagePayload";
|
||||
|
||||
/**
|
||||
* Approximation of a membership status for a given room.
|
||||
|
@ -194,6 +195,6 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
|
|||
metricsTrigger: undefined, // other
|
||||
});
|
||||
} else {
|
||||
dis.dispatch({ action: 'view_home_page' });
|
||||
dis.dispatch<ViewHomePagePayload>({ action: Action.ViewHomePage });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import CreateSpaceFromCommunityDialog from "../components/views/dialogs/CreateSp
|
|||
import SpacePreferencesDialog, { SpacePreferenceTab } from "../components/views/dialogs/SpacePreferencesDialog";
|
||||
import PosthogTrackers from "../PosthogTrackers";
|
||||
import { ButtonEvent } from "../components/views/elements/AccessibleButton";
|
||||
import { AfterLeaveRoomPayload } from "../dispatcher/payloads/AfterLeaveRoomPayload";
|
||||
|
||||
export const shouldShowSpaceSettings = (space: Room) => {
|
||||
const userId = space.client.getUserId();
|
||||
|
@ -189,8 +190,8 @@ export const leaveSpace = (space: Room) => {
|
|||
if (!leave) return;
|
||||
await bulkSpaceBehaviour(space, rooms, room => leaveRoomBehaviour(room.roomId));
|
||||
|
||||
dis.dispatch({
|
||||
action: "after_leave_room",
|
||||
dis.dispatch<AfterLeaveRoomPayload>({
|
||||
action: Action.AfterLeaveRoom,
|
||||
room_id: space.roomId,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -853,7 +853,7 @@ describe("SpaceStore", () => {
|
|||
await run();
|
||||
|
||||
dispatcherRef = defaultDispatcher.register(payload => {
|
||||
if (payload.action === Action.ViewRoom || payload.action === "view_home_page") {
|
||||
if (payload.action === Action.ViewRoom || payload.action === Action.ViewHomePage) {
|
||||
currentRoom = payload.room_id || null;
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue