diff --git a/res/css/_common.scss b/res/css/_common.scss
index 70ab2457f1..5987275f7f 100644
--- a/res/css/_common.scss
+++ b/res/css/_common.scss
@@ -550,6 +550,22 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
color: $username-variant8-color;
}
+@define-mixin mx_Tooltip_dark {
+ box-shadow: none;
+ background-color: $tooltip-timeline-bg-color;
+ color: $tooltip-timeline-fg-color;
+ border: none;
+ border-radius: 3px;
+ padding: 6px 8px;
+}
+
+// This is a workaround for our mixins not supporting child selectors
+.mx_Tooltip_dark {
+ .mx_Tooltip_chevron::after {
+ border-right-color: $tooltip-timeline-bg-color;
+ }
+}
+
@define-mixin mx_Settings_fullWidthField {
margin-right: 100px;
}
diff --git a/res/css/views/rooms/_AppsDrawer.scss b/res/css/views/rooms/_AppsDrawer.scss
index 9ca6954af7..6f5e3abade 100644
--- a/res/css/views/rooms/_AppsDrawer.scss
+++ b/res/css/views/rooms/_AppsDrawer.scss
@@ -294,49 +294,61 @@ form.mx_Custom_Widget_Form div {
.mx_AppPermissionWarning {
text-align: center;
- background-color: $primary-bg-color;
+ background-color: $widget-menu-bar-bg-color;
display: flex;
height: 100%;
flex-direction: column;
justify-content: center;
align-items: center;
+ font-size: 16px;
}
-.mx_AppPermissionWarningImage {
- margin: 10px 0;
+.mx_AppPermissionWarning_row {
+ margin-bottom: 12px;
}
-.mx_AppPermissionWarningImage img {
- width: 100px;
+.mx_AppPermissionWarning_smallText {
+ font-size: 12px;
}
-.mx_AppPermissionWarningText {
- max-width: 90%;
- margin: 10px auto 10px auto;
- color: $primary-fg-color;
+.mx_AppPermissionWarning_bolder {
+ font-weight: 600;
}
-.mx_AppPermissionWarningTextLabel {
- font-weight: bold;
- display: block;
+.mx_AppPermissionWarning h4 {
+ margin: 0;
+ padding: 0;
}
-.mx_AppPermissionWarningTextURL {
+.mx_AppPermissionWarning_helpIcon {
+ margin-top: 1px;
+ margin-right: 2px;
+ width: 10px;
+ height: 10px;
display: inline-block;
- max-width: 100%;
- color: $accent-color;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
}
-.mx_AppPermissionButton {
- border: none;
- padding: 5px 20px;
- border-radius: 5px;
- background-color: $button-bg-color;
- color: $button-fg-color;
- cursor: pointer;
+.mx_AppPermissionWarning_helpIcon::before {
+ display: inline-block;
+ background-color: $accent-color;
+ mask-repeat: no-repeat;
+ mask-size: 12px;
+ width: 12px;
+ height: 12px;
+ mask-position: center;
+ content: '';
+ vertical-align: middle;
+ mask-image: url('$(res)/img/feather-customised/help-circle.svg');
+}
+
+.mx_AppPermissionWarning_tooltip {
+ @mixin mx_Tooltip_dark;
+
+ ul {
+ list-style-position: inside;
+ padding-left: 2px;
+ margin-left: 0;
+ }
}
.mx_AppLoading {
diff --git a/src/components/views/elements/AppPermission.js b/src/components/views/elements/AppPermission.js
index 1e019c0287..422427d4c4 100644
--- a/src/components/views/elements/AppPermission.js
+++ b/src/components/views/elements/AppPermission.js
@@ -19,79 +19,123 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import url from 'url';
+import sdk from '../../../index';
import { _t } from '../../../languageHandler';
import WidgetUtils from "../../../utils/WidgetUtils";
+import MatrixClientPeg from "../../../MatrixClientPeg";
export default class AppPermission extends React.Component {
+ static propTypes = {
+ url: PropTypes.string.isRequired,
+ creatorUserId: PropTypes.string.isRequired,
+ roomId: PropTypes.string.isRequired,
+ onPermissionGranted: PropTypes.func.isRequired,
+ };
+
+ static defaultProps = {
+ onPermissionGranted: () => {},
+ };
+
constructor(props) {
super(props);
- const curlBase = this.getCurlBase();
- this.state = { curlBase: curlBase};
+ // 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
+ const room = MatrixClientPeg.get().getRoom(this.props.roomId);
+ let roomMember;
+ if (room) roomMember = room.getMember(this.props.creatorUserId);
+
+ // Set all this into the initial state
+ this.state = {
+ ...urlInfo,
+ roomMember,
+ };
}
- // Return string representation of content URL without query parameters
- getCurlBase() {
- const wurl = url.parse(this.props.url);
- let curl;
- let curlString;
+ parseWidgetUrl() {
+ const widgetUrl = url.parse(this.props.url);
+ const params = new URLSearchParams(widgetUrl.search);
- const searchParams = new URLSearchParams(wurl.search);
-
- if (WidgetUtils.isScalarUrl(wurl) && searchParams && searchParams.get('url')) {
- curl = url.parse(searchParams.get('url'));
- if (curl) {
- curl.search = curl.query = "";
- curlString = curl.format();
- }
+ // HACK: We're relying on the query params when we should be relying on the widget's `data`.
+ // This is a workaround for Scalar.
+ if (WidgetUtils.isScalarUrl(widgetUrl) && params && params.get('url')) {
+ const unwrappedUrl = url.parse(params.get('url'));
+ return {
+ widgetDomain: unwrappedUrl.host || unwrappedUrl.hostname,
+ isWrapped: true,
+ };
+ } else {
+ return {
+ widgetDomain: widgetUrl.host || widgetUrl.hostname,
+ isWrapped: false,
+ };
}
- if (!curl && wurl) {
- wurl.search = wurl.query = "";
- curlString = wurl.format();
- }
- return curlString;
}
render() {
- let e2eWarningText;
- if (this.props.isRoomEncrypted) {
- e2eWarningText =
- { _t('NOTE: Apps are not end-to-end encrypted') };
- }
- const cookieWarning =
-
- { _t('Warning: This widget might use cookies.') }
- ;
+ const AccessibleButton = sdk.getComponent("views.elements.AccessibleButton");
+ const MemberAvatar = sdk.getComponent("views.avatars.MemberAvatar");
+ const BaseAvatar = sdk.getComponent("views.avatars.BaseAvatar");
+ const TextWithTooltip = sdk.getComponent("views.elements.TextWithTooltip");
+
+ 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
+ ?