mv element.io @types __mocks__/ debian docker module_system/ playwright res src test webapp Dockerfile .dockerignore .eslintignore .stylelintrc.cjs babel.config.cjs recorder-worklet-loader.cjs .modernizr.json components.json config.json config.sample.json package.json project.json tsconfig.json tsconfig.module_system.json jest.config.ts playwright.config.ts webpack.config.ts build_config.sample.yaml apps/web/
mkdir apps/web/scripts
mv scripts/{cleanup.sh,ci_package.sh,copy-res.ts,deploy.py,package.sh} apps/web/scripts
And a couple of gitignore tweaks
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2017-2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import {
|
||||
ClientEvent,
|
||||
type MatrixClient,
|
||||
type MatrixEvent,
|
||||
MatrixEventEvent,
|
||||
type Room,
|
||||
RoomEvent,
|
||||
type IRoomTimelineData,
|
||||
type RoomState,
|
||||
RoomStateEvent,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import dis from "../dispatcher/dispatcher";
|
||||
import { type ActionPayload } from "../dispatcher/payloads";
|
||||
|
||||
/**
|
||||
* Create a MatrixActions.sync action that represents a MatrixClient `sync` event,
|
||||
* each parameter mapping to a key-value in the action.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client
|
||||
* @param {string} state the current sync state.
|
||||
* @param {string} prevState the previous sync state.
|
||||
* @returns {Object} an action of type MatrixActions.sync.
|
||||
*/
|
||||
function createSyncAction(matrixClient: MatrixClient, state: string, prevState: string): ActionPayload {
|
||||
return {
|
||||
action: "MatrixActions.sync",
|
||||
state,
|
||||
prevState,
|
||||
matrixClient,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef AccountDataAction
|
||||
* @type {Object}
|
||||
* @property {string} action 'MatrixActions.accountData'.
|
||||
* @property {MatrixEvent} event the MatrixEvent that triggered the dispatch.
|
||||
* @property {string} event_type the type of the MatrixEvent, e.g. "m.direct".
|
||||
* @property {Object} event_content the content of the MatrixEvent.
|
||||
* @property {MatrixEvent} previousEvent the previous account data event of the same type, if present
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a MatrixActions.accountData action that represents a MatrixClient `accountData`
|
||||
* matrix event.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client.
|
||||
* @param {MatrixEvent} accountDataEvent the account data event.
|
||||
* @param {MatrixEvent | undefined} previousAccountDataEvent the previous account data event of the same type, if present
|
||||
* @returns {AccountDataAction} an action of type MatrixActions.accountData.
|
||||
*/
|
||||
function createAccountDataAction(
|
||||
matrixClient: MatrixClient,
|
||||
accountDataEvent: MatrixEvent,
|
||||
previousAccountDataEvent?: MatrixEvent,
|
||||
): ActionPayload {
|
||||
return {
|
||||
action: "MatrixActions.accountData",
|
||||
event: accountDataEvent,
|
||||
event_type: accountDataEvent.getType(),
|
||||
event_content: accountDataEvent.getContent(),
|
||||
previousEvent: previousAccountDataEvent,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef RoomAccountDataAction
|
||||
* @type {Object}
|
||||
* @property {string} action 'MatrixActions.Room.accountData'.
|
||||
* @property {MatrixEvent} event the MatrixEvent that triggered the dispatch.
|
||||
* @property {string} event_type the type of the MatrixEvent, e.g. "m.direct".
|
||||
* @property {Object} event_content the content of the MatrixEvent.
|
||||
* @property {Room} room the room where the account data was changed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a MatrixActions.Room.accountData action that represents a MatrixClient `Room.accountData`
|
||||
* matrix event.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client.
|
||||
* @param {MatrixEvent} accountDataEvent the account data event.
|
||||
* @param {Room} room the room where account data was changed
|
||||
* @returns {RoomAccountDataAction} an action of type MatrixActions.Room.accountData.
|
||||
*/
|
||||
function createRoomAccountDataAction(
|
||||
matrixClient: MatrixClient,
|
||||
accountDataEvent: MatrixEvent,
|
||||
room: Room,
|
||||
): ActionPayload {
|
||||
return {
|
||||
action: "MatrixActions.Room.accountData",
|
||||
event: accountDataEvent,
|
||||
event_type: accountDataEvent.getType(),
|
||||
event_content: accountDataEvent.getContent(),
|
||||
room: room,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef RoomAction
|
||||
* @type {Object}
|
||||
* @property {string} action 'MatrixActions.Room'.
|
||||
* @property {Room} room the Room that was stored.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a MatrixActions.Room action that represents a MatrixClient `Room`
|
||||
* matrix event, emitted when a Room is stored in the client.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client.
|
||||
* @param {Room} room the Room that was stored.
|
||||
* @returns {RoomAction} an action of type `MatrixActions.Room`.
|
||||
*/
|
||||
function createRoomAction(matrixClient: MatrixClient, room: Room): ActionPayload {
|
||||
return { action: "MatrixActions.Room", room };
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef RoomTagsAction
|
||||
* @type {Object}
|
||||
* @property {string} action 'MatrixActions.Room.tags'.
|
||||
* @property {Room} room the Room whose tags changed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a MatrixActions.Room.tags action that represents a MatrixClient
|
||||
* `Room.tags` matrix event, emitted when the m.tag room account data
|
||||
* event is updated.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client.
|
||||
* @param {MatrixEvent} roomTagsEvent the m.tag event.
|
||||
* @param {Room} room the Room whose tags were changed.
|
||||
* @returns {RoomTagsAction} an action of type `MatrixActions.Room.tags`.
|
||||
*/
|
||||
function createRoomTagsAction(matrixClient: MatrixClient, roomTagsEvent: MatrixEvent, room: Room): ActionPayload {
|
||||
return { action: "MatrixActions.Room.tags", room };
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MatrixActions.Room.receipt action that represents a MatrixClient
|
||||
* `Room.receipt` event, each parameter mapping to a key-value in the action.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client
|
||||
* @param {MatrixEvent} event the receipt event.
|
||||
* @param {Room} room the room the receipt happened in.
|
||||
* @returns {Object} an action of type MatrixActions.Room.receipt.
|
||||
*/
|
||||
function createRoomReceiptAction(matrixClient: MatrixClient, event: MatrixEvent, room: Room): ActionPayload {
|
||||
return {
|
||||
action: "MatrixActions.Room.receipt",
|
||||
event,
|
||||
room,
|
||||
matrixClient,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef IRoomTimelineActionPayload
|
||||
* @type {Object}
|
||||
* @property {string} action 'MatrixActions.Room.timeline'.
|
||||
* @property {boolean} isLiveEvent whether the event was attached to a
|
||||
* live timeline.
|
||||
* @property {boolean} isLiveUnfilteredRoomTimelineEvent whether the
|
||||
* event was attached to a timeline in the set of unfiltered timelines.
|
||||
* @property {Room} room the Room whose tags changed.
|
||||
*/
|
||||
export interface IRoomTimelineActionPayload extends Pick<ActionPayload, "action"> {
|
||||
action: "MatrixActions.Room.timeline";
|
||||
event: MatrixEvent;
|
||||
room: Room | null;
|
||||
isLiveEvent?: boolean;
|
||||
isLiveUnfilteredRoomTimelineEvent: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef IRoomStateEventsActionPayload
|
||||
* @type {Object}
|
||||
* @property {string} action 'MatrixActions.RoomState.events'.
|
||||
* @property {MatrixEvent} event the state event received
|
||||
* @property {RoomState} state the room state into which the event was applied
|
||||
* @property {MatrixEvent | null} lastStateEvent the previous value for this (event-type, state-key) tuple in room state
|
||||
*/
|
||||
export interface IRoomStateEventsActionPayload extends Pick<ActionPayload, "action"> {
|
||||
action: "MatrixActions.RoomState.events";
|
||||
event: MatrixEvent;
|
||||
state: RoomState;
|
||||
lastStateEvent: MatrixEvent | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MatrixActions.Room.timeline action that represents a
|
||||
* MatrixClient `Room.timeline` matrix event, emitted when an event
|
||||
* is added to or removed from a timeline of a room.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client.
|
||||
* @param {MatrixEvent} timelineEvent the event that was added/removed.
|
||||
* @param {?Room} room the Room that was stored.
|
||||
* @param {boolean} toStartOfTimeline whether the event is being added
|
||||
* to the start (and not the end) of the timeline.
|
||||
* @param {boolean} removed whether the event was removed from the
|
||||
* timeline.
|
||||
* @param {Object} data
|
||||
* @param {boolean} data.liveEvent whether the event is a live event,
|
||||
* belonging to a live timeline.
|
||||
* @param {EventTimeline} data.timeline the timeline being altered.
|
||||
* @returns {IRoomTimelineActionPayload} an action of type `MatrixActions.Room.timeline`.
|
||||
*/
|
||||
function createRoomTimelineAction(
|
||||
matrixClient: MatrixClient,
|
||||
timelineEvent: MatrixEvent,
|
||||
room: Room | null,
|
||||
toStartOfTimeline: boolean,
|
||||
removed: boolean,
|
||||
data: IRoomTimelineData,
|
||||
): IRoomTimelineActionPayload {
|
||||
return {
|
||||
action: "MatrixActions.Room.timeline",
|
||||
event: timelineEvent,
|
||||
isLiveEvent: data.liveEvent,
|
||||
isLiveUnfilteredRoomTimelineEvent: data.timeline.getTimelineSet() === room?.getUnfilteredTimelineSet(),
|
||||
room,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MatrixActions.Room.timeline action that represents a
|
||||
* MatrixClient `Room.timeline` matrix event, emitted when an event
|
||||
* is added to or removed from a timeline of a room.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client.
|
||||
* @param {MatrixEvent} event the state event received
|
||||
* @param {RoomState} state the room state into which the event was applied
|
||||
* @param {MatrixEvent | null} lastStateEvent the previous value for this (event-type, state-key) tuple in room state
|
||||
* @returns {IRoomStateEventsActionPayload} an action of type `MatrixActions.RoomState.events`.
|
||||
*/
|
||||
function createRoomStateEventsAction(
|
||||
matrixClient: MatrixClient,
|
||||
event: MatrixEvent,
|
||||
state: RoomState,
|
||||
lastStateEvent: MatrixEvent | null,
|
||||
): IRoomStateEventsActionPayload {
|
||||
return {
|
||||
action: "MatrixActions.RoomState.events",
|
||||
event,
|
||||
state,
|
||||
lastStateEvent,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef RoomMembershipAction
|
||||
* @type {Object}
|
||||
* @property {string} action 'MatrixActions.Room.myMembership'.
|
||||
* @property {Room} room to room for which the self-membership changed.
|
||||
* @property {string} membership the new membership
|
||||
* @property {string} oldMembership the previous membership, can be null.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a MatrixActions.Room.myMembership action that represents
|
||||
* a MatrixClient `Room.myMembership` event for the syncing user,
|
||||
* emitted when the syncing user's membership is updated for a room.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client.
|
||||
* @param {Room} room to room for which the self-membership changed.
|
||||
* @param {string} membership the new membership
|
||||
* @param {string} oldMembership the previous membership, can be null.
|
||||
* @returns {RoomMembershipAction} an action of type `MatrixActions.Room.myMembership`.
|
||||
*/
|
||||
function createSelfMembershipAction(
|
||||
matrixClient: MatrixClient,
|
||||
room: Room,
|
||||
membership: string,
|
||||
oldMembership: string,
|
||||
): ActionPayload {
|
||||
return { action: "MatrixActions.Room.myMembership", room, membership, oldMembership };
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef EventDecryptedAction
|
||||
* @type {Object}
|
||||
* @property {string} action 'MatrixActions.Event.decrypted'.
|
||||
* @property {MatrixEvent} event the matrix event that was decrypted.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a MatrixActions.Event.decrypted action that represents
|
||||
* a MatrixClient `Event.decrypted` matrix event, emitted when a
|
||||
* matrix event is decrypted.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client.
|
||||
* @param {MatrixEvent} event the matrix event that was decrypted.
|
||||
* @returns {EventDecryptedAction} an action of type `MatrixActions.Event.decrypted`.
|
||||
*/
|
||||
function createEventDecryptedAction(matrixClient: MatrixClient, event: MatrixEvent): ActionPayload {
|
||||
return { action: "MatrixActions.Event.decrypted", event };
|
||||
}
|
||||
|
||||
type Listener = () => void;
|
||||
type ActionCreator = (matrixClient: MatrixClient, ...args: any) => ActionPayload;
|
||||
|
||||
// A list of callbacks to call to unregister all listeners added
|
||||
let matrixClientListenersStop: Listener[] = [];
|
||||
|
||||
/**
|
||||
* Start listening to events of type eventName on matrixClient and when they are emitted,
|
||||
* dispatch an action created by the actionCreator function.
|
||||
* @param {MatrixClient} matrixClient a MatrixClient to register a listener with.
|
||||
* @param {string} eventName the event to listen to on MatrixClient.
|
||||
* @param {function} actionCreator a function that should return an action to dispatch
|
||||
* when given the MatrixClient as an argument as well as
|
||||
* arguments emitted in the MatrixClient event.
|
||||
*/
|
||||
function addMatrixClientListener(
|
||||
matrixClient: MatrixClient,
|
||||
eventName: Parameters<MatrixClient["emit"]>[0],
|
||||
actionCreator: ActionCreator,
|
||||
): void {
|
||||
const listener: Listener = (...args) => {
|
||||
const payload = actionCreator(matrixClient, ...args);
|
||||
if (payload) {
|
||||
// Consumers shouldn't have to worry about calling js-sdk methods mid-dispatch, so make this dispatch async
|
||||
dis.dispatch(payload, false);
|
||||
}
|
||||
};
|
||||
matrixClient.on(eventName, listener);
|
||||
matrixClientListenersStop.push(() => {
|
||||
matrixClient.removeListener(eventName, listener);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This object is responsible for dispatching actions when certain events are emitted by
|
||||
* the given MatrixClient.
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* Start listening to certain events from the MatrixClient and dispatch actions when
|
||||
* they are emitted.
|
||||
* @param {MatrixClient} matrixClient the MatrixClient to listen to events from
|
||||
*/
|
||||
start(matrixClient: MatrixClient) {
|
||||
addMatrixClientListener(matrixClient, ClientEvent.Sync, createSyncAction);
|
||||
addMatrixClientListener(matrixClient, ClientEvent.AccountData, createAccountDataAction);
|
||||
addMatrixClientListener(matrixClient, RoomEvent.AccountData, createRoomAccountDataAction);
|
||||
addMatrixClientListener(matrixClient, ClientEvent.Room, createRoomAction);
|
||||
addMatrixClientListener(matrixClient, RoomEvent.Tags, createRoomTagsAction);
|
||||
addMatrixClientListener(matrixClient, RoomEvent.Receipt, createRoomReceiptAction);
|
||||
addMatrixClientListener(matrixClient, RoomEvent.Timeline, createRoomTimelineAction);
|
||||
addMatrixClientListener(matrixClient, RoomEvent.MyMembership, createSelfMembershipAction);
|
||||
addMatrixClientListener(matrixClient, MatrixEventEvent.Decrypted, createEventDecryptedAction);
|
||||
addMatrixClientListener(matrixClient, RoomStateEvent.Events, createRoomStateEventsAction);
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop listening to events.
|
||||
*/
|
||||
stop() {
|
||||
matrixClientListenersStop.forEach((stopListener) => stopListener());
|
||||
matrixClientListenersStop = [];
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2018 New Vector Ltd
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type MatrixClient, type Room } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { asyncAction } from "./actionCreators";
|
||||
import Modal from "../Modal";
|
||||
import * as Rooms from "../Rooms";
|
||||
import { _t } from "../languageHandler";
|
||||
import { type AsyncActionPayload } from "../dispatcher/payloads";
|
||||
import RoomListStore from "../stores/room-list/RoomListStore";
|
||||
import { SortAlgorithm } from "../stores/room-list/algorithms/models";
|
||||
import { DefaultTagID, type TagID } from "../stores/room-list/models";
|
||||
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
|
||||
|
||||
export default class RoomListActions {
|
||||
/**
|
||||
* Creates an action thunk that will do an asynchronous request to
|
||||
* tag room.
|
||||
*
|
||||
* @param {MatrixClient} matrixClient the matrix client to set the
|
||||
* account data on.
|
||||
* @param {Room} room the room to tag.
|
||||
* @param {string} oldTag the tag to remove (unless oldTag ==== newTag)
|
||||
* @param {string} newTag the tag with which to tag the room.
|
||||
* @param {?number} oldIndex the previous position of the room in the
|
||||
* list of rooms.
|
||||
* @param {?number} newIndex the new position of the room in the list
|
||||
* of rooms.
|
||||
* @returns {AsyncActionPayload} an async action payload
|
||||
* @see asyncAction
|
||||
*/
|
||||
public static tagRoom(
|
||||
matrixClient: MatrixClient,
|
||||
room: Room,
|
||||
oldTag: TagID | null,
|
||||
newTag: TagID | null,
|
||||
newIndex: number,
|
||||
): AsyncActionPayload {
|
||||
let metaData: Parameters<MatrixClient["setRoomTag"]>[2] | undefined;
|
||||
|
||||
// Is the tag ordered manually?
|
||||
const store = RoomListStore.instance;
|
||||
if (newTag && store.getTagSorting(newTag) === SortAlgorithm.Manual) {
|
||||
const newList = [...store.orderedLists[newTag]];
|
||||
|
||||
newList.sort((a, b) => a.tags[newTag].order - b.tags[newTag].order);
|
||||
|
||||
const indexBefore = newIndex - 1;
|
||||
const indexAfter = newIndex;
|
||||
|
||||
const prevOrder = indexBefore <= 0 ? 0 : newList[indexBefore].tags[newTag].order;
|
||||
const nextOrder = indexAfter >= newList.length ? 1 : newList[indexAfter].tags[newTag].order;
|
||||
|
||||
metaData = {
|
||||
order: (prevOrder + nextOrder) / 2.0,
|
||||
};
|
||||
}
|
||||
|
||||
return asyncAction(
|
||||
"RoomListActions.tagRoom",
|
||||
() => {
|
||||
const promises: Promise<any>[] = [];
|
||||
const roomId = room.roomId;
|
||||
|
||||
// Evil hack to get DMs behaving
|
||||
if (
|
||||
(oldTag === undefined && newTag === DefaultTagID.DM) ||
|
||||
(oldTag === DefaultTagID.DM && newTag === undefined)
|
||||
) {
|
||||
return Rooms.guessAndSetDMRoom(room, newTag === DefaultTagID.DM).catch((err) => {
|
||||
logger.error("Failed to set DM tag " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("room_list|failed_set_dm_tag"),
|
||||
description: err?.message ?? _t("invite|failed_generic"),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const hasChangedSubLists = oldTag !== newTag;
|
||||
|
||||
// More evilness: We will still be dealing with moving to favourites/low prio,
|
||||
// but we avoid ever doing a request with TAG_DM.
|
||||
//
|
||||
// if we moved lists, remove the old tag
|
||||
if (oldTag && oldTag !== DefaultTagID.DM && hasChangedSubLists) {
|
||||
const promiseToDelete = matrixClient.deleteRoomTag(roomId, oldTag).catch(function (err) {
|
||||
logger.error("Failed to remove tag " + oldTag + " from room: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("room_list|failed_remove_tag", { tagName: oldTag }),
|
||||
description: err?.message ?? _t("invite|failed_generic"),
|
||||
});
|
||||
});
|
||||
|
||||
promises.push(promiseToDelete);
|
||||
}
|
||||
|
||||
// if we moved lists or the ordering changed, add the new tag
|
||||
if (newTag && newTag !== DefaultTagID.DM && (hasChangedSubLists || metaData)) {
|
||||
const promiseToAdd = matrixClient.setRoomTag(roomId, newTag, metaData).catch(function (err) {
|
||||
logger.error("Failed to add tag " + newTag + " to room: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("room_list|failed_add_tag", { tagName: newTag }),
|
||||
description: err?.message ?? _t("invite|failed_generic"),
|
||||
});
|
||||
|
||||
throw err;
|
||||
});
|
||||
|
||||
promises.push(promiseToAdd);
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
},
|
||||
() => {
|
||||
// For an optimistic update
|
||||
return {
|
||||
room,
|
||||
oldTag,
|
||||
newTag,
|
||||
metaData,
|
||||
};
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2017 New Vector Ltd
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type AsyncActionFn, AsyncActionPayload } from "../dispatcher/payloads";
|
||||
|
||||
/**
|
||||
* Create an action thunk that will dispatch actions indicating the current
|
||||
* status of the Promise returned by fn.
|
||||
*
|
||||
* @param {string} id the id to give the dispatched actions. This is given a
|
||||
* suffix determining whether it is pending, successful or
|
||||
* a failure.
|
||||
* @param {function} fn a function that returns a Promise.
|
||||
* @param {function?} pendingFn a function that returns an object to assign
|
||||
* to the `request` key of the ${id}.pending
|
||||
* payload.
|
||||
* @returns {AsyncActionPayload} an async action payload. Includes a function
|
||||
* that uses its single argument as a dispatch function
|
||||
* to dispatch the following actions:
|
||||
* `${id}.pending` and either
|
||||
* `${id}.success` or
|
||||
* `${id}.failure`.
|
||||
*
|
||||
* The shape of each are:
|
||||
* { action: '${id}.pending', request }
|
||||
* { action: '${id}.success', result }
|
||||
* { action: '${id}.failure', err }
|
||||
*
|
||||
* where `request` is returned by `pendingFn` and
|
||||
* result is the result of the promise returned by
|
||||
* `fn`.
|
||||
*/
|
||||
export function asyncAction(id: string, fn: () => Promise<any>, pendingFn: () => any | null): AsyncActionPayload {
|
||||
const helper: AsyncActionFn = (dispatch) => {
|
||||
dispatch({
|
||||
action: id + ".pending",
|
||||
request: typeof pendingFn === "function" ? pendingFn() : undefined,
|
||||
});
|
||||
fn()
|
||||
.then((result) => {
|
||||
dispatch({ action: id + ".success", result });
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch({ action: id + ".failure", err });
|
||||
});
|
||||
};
|
||||
return new AsyncActionPayload(helper);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { UserTab } from "../../components/views/dialogs/UserTab";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
||||
|
||||
/**
|
||||
* Open user device manager settings
|
||||
*/
|
||||
export const viewUserDeviceSettings = (): void => {
|
||||
defaultDispatcher.dispatch({
|
||||
action: Action.ViewUserSettings,
|
||||
initialTabId: UserTab.SessionManager,
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user