2019-07-23 17:52:00 +01:00
|
|
|
/*
|
|
|
|
|
Copyright 2017 Vector Creations Ltd
|
|
|
|
|
Copyright 2018, 2019 New Vector Ltd
|
2020-07-10 19:07:11 +01:00
|
|
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
2019-07-23 17:52:00 +01:00
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-07-26 11:28:43 +01:00
|
|
|
import React from "react";
|
2023-08-04 12:22:08 +01:00
|
|
|
import { RoomMember } from "matrix-js-sdk/src/matrix";
|
2021-10-22 17:23:32 -05:00
|
|
|
|
2017-07-28 16:39:18 +01:00
|
|
|
import { _t } from "../../../languageHandler";
|
2020-07-10 19:07:11 +01:00
|
|
|
import SdkConfig from "../../../SdkConfig";
|
2018-06-26 11:59:16 +01:00
|
|
|
import WidgetUtils from "../../../utils/WidgetUtils";
|
2021-06-29 13:11:58 +01:00
|
|
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
2021-07-20 12:42:21 +02:00
|
|
|
import MemberAvatar from "../avatars/MemberAvatar";
|
|
|
|
|
import BaseAvatar from "../avatars/BaseAvatar";
|
2023-06-14 11:11:06 +00:00
|
|
|
import Heading from "../typography/Heading";
|
2021-07-20 12:42:21 +02:00
|
|
|
import AccessibleButton from "./AccessibleButton";
|
|
|
|
|
import TextWithTooltip from "./TextWithTooltip";
|
2023-05-17 12:50:00 +01:00
|
|
|
import { parseUrl } from "../../../utils/UrlUtils";
|
2023-06-14 11:11:06 +00:00
|
|
|
import { Icon as HelpIcon } from "../../../../res/img/feather-customised/help-circle.svg";
|
2021-07-20 12:19:00 +02:00
|
|
|
|
|
|
|
|
interface IProps {
|
|
|
|
|
url: string;
|
|
|
|
|
creatorUserId: string;
|
|
|
|
|
roomId: string;
|
|
|
|
|
onPermissionGranted: () => void;
|
|
|
|
|
isRoomEncrypted?: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface IState {
|
2023-05-16 14:25:43 +01:00
|
|
|
roomMember: RoomMember | null;
|
2021-07-20 12:19:00 +02:00
|
|
|
isWrapped: boolean;
|
2023-03-29 08:23:54 +01:00
|
|
|
widgetDomain: string | null;
|
2021-07-20 12:19:00 +02:00
|
|
|
}
|
2017-07-26 11:28:43 +01:00
|
|
|
|
2021-07-20 12:19:00 +02:00
|
|
|
export default class AppPermission extends React.Component<IProps, IState> {
|
2022-12-16 12:29:59 +00:00
|
|
|
public static defaultProps: Partial<IProps> = {
|
2019-11-15 14:25:53 -07:00
|
|
|
onPermissionGranted: () => {},
|
|
|
|
|
};
|
|
|
|
|
|
2022-12-16 12:29:59 +00:00
|
|
|
public constructor(props: IProps) {
|
2017-07-26 11:28:43 +01:00
|
|
|
super(props);
|
|
|
|
|
|
2019-11-15 14:25:53 -07:00
|
|
|
// The first step is to pick apart the widget so we can render information about it
|
|
|
|
|
const urlInfo = this.parseWidgetUrl();
|
|
|
|
|
|
|
|
|
|
// The second step is to find the user's profile so we can show it on the prompt
|
2023-06-15 08:46:19 +01:00
|
|
|
const room = MatrixClientPeg.safeGet().getRoom(this.props.roomId);
|
2023-05-16 14:25:43 +01:00
|
|
|
let roomMember: RoomMember | null = null;
|
2019-11-15 14:25:53 -07:00
|
|
|
if (room) roomMember = room.getMember(this.props.creatorUserId);
|
|
|
|
|
|
|
|
|
|
// Set all this into the initial state
|
|
|
|
|
this.state = {
|
2021-08-06 13:54:00 +02:00
|
|
|
roomMember,
|
|
|
|
|
...urlInfo,
|
2019-11-15 14:25:53 -07:00
|
|
|
};
|
2017-07-26 11:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 08:23:54 +01:00
|
|
|
private parseWidgetUrl(): { isWrapped: boolean; widgetDomain: string | null } {
|
2023-05-17 12:50:00 +01:00
|
|
|
const widgetUrl = parseUrl(this.props.url);
|
2017-07-26 16:47:58 +01:00
|
|
|
|
2019-11-15 14:25:53 -07:00
|
|
|
// HACK: We're relying on the query params when we should be relying on the widget's `data`.
|
|
|
|
|
// This is a workaround for Scalar.
|
2023-05-17 12:50:00 +01:00
|
|
|
if (WidgetUtils.isScalarUrl(this.props.url) && widgetUrl.searchParams.has("url")) {
|
|
|
|
|
const unwrappedUrl = parseUrl(widgetUrl.searchParams.get("url")!);
|
2019-11-15 14:25:53 -07:00
|
|
|
return {
|
|
|
|
|
widgetDomain: unwrappedUrl.host || unwrappedUrl.hostname,
|
|
|
|
|
isWrapped: true,
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
return {
|
|
|
|
|
widgetDomain: widgetUrl.host || widgetUrl.hostname,
|
|
|
|
|
isWrapped: false,
|
|
|
|
|
};
|
2017-07-26 11:28:43 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-13 17:01:43 +00:00
|
|
|
public render(): React.ReactNode {
|
2020-07-10 19:07:11 +01:00
|
|
|
const brand = SdkConfig.get().brand;
|
2019-11-15 14:25:53 -07:00
|
|
|
|
|
|
|
|
const displayName = this.state.roomMember ? this.state.roomMember.name : this.props.creatorUserId;
|
|
|
|
|
const userId = displayName === this.props.creatorUserId ? null : this.props.creatorUserId;
|
|
|
|
|
|
|
|
|
|
const avatar = this.state.roomMember ? (
|
|
|
|
|
<MemberAvatar member={this.state.roomMember} width={38} height={38} />
|
|
|
|
|
) : (
|
|
|
|
|
<BaseAvatar name={this.props.creatorUserId} width={38} height={38} />
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const warningTooltipText = (
|
|
|
|
|
<div>
|
2021-07-20 12:19:00 +02:00
|
|
|
{_t("Any of the following data may be shared:")}
|
2019-11-15 14:25:53 -07:00
|
|
|
<ul>
|
2021-07-20 12:19:00 +02:00
|
|
|
<li>{_t("Your display name")}</li>
|
2023-07-07 04:54:43 -06:00
|
|
|
<li>{_t("Your profile picture URL")}</li>
|
2021-07-20 12:19:00 +02:00
|
|
|
<li>{_t("Your user ID")}</li>
|
2023-05-23 15:35:31 +02:00
|
|
|
<li>{_t("Your device ID")}</li>
|
2021-07-20 12:19:00 +02:00
|
|
|
<li>{_t("Your theme")}</li>
|
2023-05-23 15:35:31 +02:00
|
|
|
<li>{_t("Your language")}</li>
|
2021-07-20 12:19:00 +02:00
|
|
|
<li>{_t("%(brand)s URL", { brand })}</li>
|
|
|
|
|
<li>{_t("Room ID")}</li>
|
|
|
|
|
<li>{_t("Widget ID")}</li>
|
2019-11-15 14:25:53 -07:00
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
const warningTooltip = (
|
|
|
|
|
<TextWithTooltip
|
|
|
|
|
tooltip={warningTooltipText}
|
2023-05-17 08:51:18 +00:00
|
|
|
tooltipClass="mx_Tooltip--appPermission mx_Tooltip--appPermission--dark"
|
2023-06-14 11:11:06 +00:00
|
|
|
class="mx_TextWithTooltip_target--helpIcon"
|
2019-11-15 14:25:53 -07:00
|
|
|
>
|
2023-06-14 11:11:06 +00:00
|
|
|
<HelpIcon className="mx_Icon mx_Icon_12" />
|
2019-11-15 14:25:53 -07:00
|
|
|
</TextWithTooltip>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Due to i18n limitations, we can't dedupe the code for variables in these two messages.
|
|
|
|
|
const warning = this.state.isWrapped
|
2021-07-13 16:04:50 +01:00
|
|
|
? _t(
|
|
|
|
|
"Using this widget may share data <helpIcon /> with %(widgetDomain)s & your integration manager.",
|
2021-06-29 13:11:58 +01:00
|
|
|
{ widgetDomain: this.state.widgetDomain },
|
|
|
|
|
{ helpIcon: () => warningTooltip },
|
|
|
|
|
)
|
2019-11-15 14:25:53 -07:00
|
|
|
: _t(
|
|
|
|
|
"Using this widget may share data <helpIcon /> with %(widgetDomain)s.",
|
2021-06-29 13:11:58 +01:00
|
|
|
{ widgetDomain: this.state.widgetDomain },
|
|
|
|
|
{ helpIcon: () => warningTooltip },
|
|
|
|
|
);
|
2019-11-15 14:25:53 -07:00
|
|
|
|
2019-11-21 09:12:07 -07:00
|
|
|
const encryptionWarning = this.props.isRoomEncrypted ? _t("Widgets do not use message encryption.") : null;
|
2019-11-20 16:26:06 -07:00
|
|
|
|
2017-07-26 11:28:43 +01:00
|
|
|
return (
|
2023-05-16 10:14:52 +00:00
|
|
|
<div className="mx_AppPermission">
|
2023-06-14 11:11:06 +00:00
|
|
|
<div className="mx_AppPermission_content">
|
|
|
|
|
<div className="mx_AppPermission_content_bolder">{_t("Widget added by")}</div>
|
|
|
|
|
<div>
|
|
|
|
|
{avatar}
|
2023-06-29 11:30:25 +01:00
|
|
|
<Heading size="4">{displayName}</Heading>
|
2023-06-14 11:11:06 +00:00
|
|
|
<div>{userId}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div>{warning}</div>
|
|
|
|
|
<div>
|
|
|
|
|
{_t("This widget may use cookies.")} {encryptionWarning}
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<AccessibleButton kind="primary_sm" onClick={this.props.onPermissionGranted}>
|
2023-08-22 20:55:15 +01:00
|
|
|
{_t("action|continue")}
|
2023-06-14 11:11:06 +00:00
|
|
|
</AccessibleButton>
|
|
|
|
|
</div>
|
2017-07-26 16:47:58 +01:00
|
|
|
</div>
|
2017-07-26 11:28:43 +01:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|