Widget permissions customizations using module api (#10121)
* Using module api to customize widget permissions Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net> * Revert type export and use ComponentProps instead. Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net> --------- Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net> Co-authored-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net>
This commit is contained in:
parent
9a0e537916
commit
7b77f76486
11 changed files with 241 additions and 31 deletions
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
import React, { useContext } from "react";
|
||||
import { MatrixCapabilities } from "matrix-widget-api";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { ApprovalOpts, WidgetLifecycle } from "@matrix-org/react-sdk-module-api/lib/lifecycles/WidgetLifecycle";
|
||||
|
||||
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from "./IconizedContextMenu";
|
||||
import { ChevronFace } from "../../structures/ContextMenu";
|
||||
|
@ -34,6 +35,8 @@ import { WidgetType } from "../../../widgets/WidgetType";
|
|||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
|
||||
import { getConfigLivestreamUrl, startJitsiAudioLivestream } from "../../../Livestream";
|
||||
import { ModuleRunner } from "../../../modules/ModuleRunner";
|
||||
import { ElementWidget } from "../../../stores/widgets/StopGapWidget";
|
||||
|
||||
interface IProps extends React.ComponentProps<typeof IconizedContextMenu> {
|
||||
app: IApp;
|
||||
|
@ -45,7 +48,7 @@ interface IProps extends React.ComponentProps<typeof IconizedContextMenu> {
|
|||
onEditClick?(): void;
|
||||
}
|
||||
|
||||
const WidgetContextMenu: React.FC<IProps> = ({
|
||||
export const WidgetContextMenu: React.FC<IProps> = ({
|
||||
onFinished,
|
||||
app,
|
||||
userWidget,
|
||||
|
@ -158,24 +161,31 @@ const WidgetContextMenu: React.FC<IProps> = ({
|
|||
const isLocalWidget = WidgetType.JITSI.matches(app.type);
|
||||
let revokeButton;
|
||||
if (!userWidget && !isLocalWidget && isAllowedWidget) {
|
||||
const onRevokeClick = (): void => {
|
||||
logger.info("Revoking permission for widget to load: " + app.eventId);
|
||||
const current = SettingsStore.getValue("allowedWidgets", roomId);
|
||||
if (app.eventId !== undefined) current[app.eventId] = false;
|
||||
const level = SettingsStore.firstSupportedLevel("allowedWidgets");
|
||||
SettingsStore.setValue("allowedWidgets", roomId, level, current).catch((err) => {
|
||||
logger.error(err);
|
||||
// We don't really need to do anything about this - the user will just hit the button again.
|
||||
});
|
||||
onFinished();
|
||||
};
|
||||
const opts: ApprovalOpts = { approved: undefined };
|
||||
ModuleRunner.instance.invoke(WidgetLifecycle.PreLoadRequest, opts, new ElementWidget(app));
|
||||
|
||||
revokeButton = <IconizedContextMenuOption onClick={onRevokeClick} label={_t("Revoke permissions")} />;
|
||||
if (!opts.approved) {
|
||||
const onRevokeClick = (): void => {
|
||||
logger.info("Revoking permission for widget to load: " + app.eventId);
|
||||
const current = SettingsStore.getValue("allowedWidgets", roomId);
|
||||
if (app.eventId !== undefined) current[app.eventId] = false;
|
||||
const level = SettingsStore.firstSupportedLevel("allowedWidgets");
|
||||
if (!level) throw new Error("level must be defined");
|
||||
SettingsStore.setValue("allowedWidgets", roomId ?? null, level, current).catch((err) => {
|
||||
logger.error(err);
|
||||
// We don't really need to do anything about this - the user will just hit the button again.
|
||||
});
|
||||
onFinished();
|
||||
};
|
||||
|
||||
revokeButton = <IconizedContextMenuOption onClick={onRevokeClick} label={_t("Revoke permissions")} />;
|
||||
}
|
||||
}
|
||||
|
||||
let moveLeftButton;
|
||||
if (showUnpin && widgetIndex > 0) {
|
||||
const onClick = (): void => {
|
||||
if (!room) throw new Error("room must be defined");
|
||||
WidgetLayoutStore.instance.moveWithinContainer(room, Container.Top, app, -1);
|
||||
onFinished();
|
||||
};
|
||||
|
@ -207,5 +217,3 @@ const WidgetContextMenu: React.FC<IProps> = ({
|
|||
</IconizedContextMenu>
|
||||
);
|
||||
};
|
||||
|
||||
export default WidgetContextMenu;
|
||||
|
|
|
@ -23,6 +23,7 @@ import classNames from "classnames";
|
|||
import { MatrixCapabilities } from "matrix-widget-api";
|
||||
import { Room, RoomEvent } from "matrix-js-sdk/src/models/room";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { ApprovalOpts, WidgetLifecycle } from "@matrix-org/react-sdk-module-api/lib/lifecycles/WidgetLifecycle";
|
||||
|
||||
import AccessibleButton from "./AccessibleButton";
|
||||
import { _t } from "../../../languageHandler";
|
||||
|
@ -36,7 +37,7 @@ import { aboveLeftOf, ContextMenuButton } from "../../structures/ContextMenu";
|
|||
import PersistedElement, { getPersistKey } from "./PersistedElement";
|
||||
import { WidgetType } from "../../../widgets/WidgetType";
|
||||
import { ElementWidget, StopGapWidget } from "../../../stores/widgets/StopGapWidget";
|
||||
import WidgetContextMenu from "../context_menus/WidgetContextMenu";
|
||||
import { WidgetContextMenu } from "../context_menus/WidgetContextMenu";
|
||||
import WidgetAvatar from "../avatars/WidgetAvatar";
|
||||
import LegacyCallHandler from "../../../LegacyCallHandler";
|
||||
import { IApp } from "../../../stores/WidgetStore";
|
||||
|
@ -50,6 +51,7 @@ import { Action } from "../../../dispatcher/actions";
|
|||
import { ElementWidgetCapabilities } from "../../../stores/widgets/ElementWidgetCapabilities";
|
||||
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";
|
||||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
||||
import { ModuleRunner } from "../../../modules/ModuleRunner";
|
||||
|
||||
interface IProps {
|
||||
app: IApp;
|
||||
|
@ -162,6 +164,9 @@ export default class AppTile extends React.Component<IProps, IState> {
|
|||
private hasPermissionToLoad = (props: IProps): boolean => {
|
||||
if (this.usingLocalWidget()) return true;
|
||||
if (!props.room) return true; // user widgets always have permissions
|
||||
const opts: ApprovalOpts = { approved: undefined };
|
||||
ModuleRunner.instance.invoke(WidgetLifecycle.PreLoadRequest, opts, new ElementWidget(this.props.app));
|
||||
if (opts.approved) return true;
|
||||
|
||||
const currentlyAllowedWidgets = SettingsStore.getValue("allowedWidgets", props.room.roomId);
|
||||
const allowed = props.app.eventId !== undefined && (currentlyAllowedWidgets[props.app.eventId] ?? false);
|
||||
|
|
|
@ -40,7 +40,7 @@ import { E2EStatus } from "../../../utils/ShieldUtils";
|
|||
import RoomContext from "../../../contexts/RoomContext";
|
||||
import { UIComponent, UIFeature } from "../../../settings/UIFeature";
|
||||
import { ChevronFace, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu";
|
||||
import WidgetContextMenu from "../context_menus/WidgetContextMenu";
|
||||
import { WidgetContextMenu } from "../context_menus/WidgetContextMenu";
|
||||
import { useRoomMemberCount } from "../../../hooks/useRoomMembers";
|
||||
import { useFeatureEnabled } from "../../../hooks/useSettings";
|
||||
import { usePinnedEvents } from "./PinnedMessagesCard";
|
||||
|
|
|
@ -24,7 +24,7 @@ import AppTile from "../elements/AppTile";
|
|||
import { _t } from "../../../languageHandler";
|
||||
import { useWidgets } from "./RoomSummaryCard";
|
||||
import { ChevronFace, ContextMenuButton, useContextMenu } from "../../structures/ContextMenu";
|
||||
import WidgetContextMenu from "../context_menus/WidgetContextMenu";
|
||||
import { WidgetContextMenu } from "../context_menus/WidgetContextMenu";
|
||||
import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
|
||||
import UIStore from "../../../stores/UIStore";
|
||||
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue