Merge pull request #6012 from matrix-org/t3chguy/fix/17238
Add feedback mechanism for beta features, namely Spaces
This commit is contained in:
commit
ea9be0dd4c
14 changed files with 318 additions and 17 deletions
|
@ -63,6 +63,7 @@
|
||||||
@import "./views/dialogs/_AddExistingToSpaceDialog.scss";
|
@import "./views/dialogs/_AddExistingToSpaceDialog.scss";
|
||||||
@import "./views/dialogs/_AddressPickerDialog.scss";
|
@import "./views/dialogs/_AddressPickerDialog.scss";
|
||||||
@import "./views/dialogs/_Analytics.scss";
|
@import "./views/dialogs/_Analytics.scss";
|
||||||
|
@import "./views/dialogs/_BetaFeedbackDialog.scss";
|
||||||
@import "./views/dialogs/_BugReportDialog.scss";
|
@import "./views/dialogs/_BugReportDialog.scss";
|
||||||
@import "./views/dialogs/_ChangelogDialog.scss";
|
@import "./views/dialogs/_ChangelogDialog.scss";
|
||||||
@import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss";
|
@import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss";
|
||||||
|
|
|
@ -93,6 +93,10 @@ $SpaceRoomViewInnerWidth: 428px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(.mx_SpaceRoomView_landing) .mx_SpaceFeedbackPrompt {
|
||||||
|
width: $SpaceRoomViewInnerWidth;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_SpaceRoomView_buttons {
|
.mx_SpaceRoomView_buttons {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 44px;
|
margin-top: 44px;
|
||||||
|
@ -335,10 +339,19 @@ $SpaceRoomViewInnerWidth: 428px;
|
||||||
.mx_SearchBox {
|
.mx_SearchBox {
|
||||||
margin: 0 0 20px;
|
margin: 0 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_SpaceFeedbackPrompt {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
// hide the HR as we have our own
|
||||||
|
& + hr {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_SpaceRoomView_privateScope {
|
.mx_SpaceRoomView_privateScope {
|
||||||
.mx_AccessibleButton {
|
> .mx_AccessibleButton {
|
||||||
@mixin SpacePillButton;
|
@mixin SpacePillButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,3 +463,66 @@ $SpaceRoomViewInnerWidth: 428px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_SpaceFeedbackPrompt {
|
||||||
|
margin-top: 18px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
> hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid $input-border-color;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: $font-15px;
|
||||||
|
line-height: $font-24px;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
color: $secondary-fg-color;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 32px;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 2px;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
background-color: $secondary-fg-color;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-size: contain;
|
||||||
|
mask-image: url('$(res)/img/element-icons/room/room-summary.svg');
|
||||||
|
mask-position: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AccessibleButton_kind_link {
|
||||||
|
color: $accent-color;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 0 0 24px;
|
||||||
|
margin-left: 8px;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
background-color: $accent-color;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-size: contain;
|
||||||
|
mask-image: url('$(res)/img/element-icons/chat-bubbles.svg');
|
||||||
|
mask-position: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,19 +39,21 @@ limitations under the License.
|
||||||
font-size: $font-15px;
|
font-size: $font-15px;
|
||||||
line-height: $font-20px;
|
line-height: $font-20px;
|
||||||
color: $secondary-fg-color;
|
color: $secondary-fg-color;
|
||||||
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_AccessibleButton {
|
.mx_AccessibleButton {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 20px 0;
|
margin: 12px 0;
|
||||||
padding: 12px 40px;
|
padding: 7px 40px;
|
||||||
width: max-content;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_BetaCard_disclaimer {
|
.mx_BetaCard_disclaimer {
|
||||||
font-size: $font-12px;
|
font-size: $font-12px;
|
||||||
line-height: $font-15px;
|
line-height: $font-15px;
|
||||||
color: $secondary-fg-color;
|
color: $secondary-fg-color;
|
||||||
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
30
res/css/views/dialogs/_BetaFeedbackDialog.scss
Normal file
30
res/css/views/dialogs/_BetaFeedbackDialog.scss
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_BetaFeedbackDialog {
|
||||||
|
.mx_BetaFeedbackDialog_subheading {
|
||||||
|
color: $secondary-fg-color;
|
||||||
|
font-size: $font-14px;
|
||||||
|
line-height: $font-20px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AccessibleButton_kind_link {
|
||||||
|
padding: 0;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
}
|
|
@ -574,7 +574,7 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
|
||||||
return <>
|
return <>
|
||||||
<SearchBox
|
<SearchBox
|
||||||
className="mx_textinput_icon mx_textinput_search"
|
className="mx_textinput_icon mx_textinput_search"
|
||||||
placeholder={ _t("Search names and description") }
|
placeholder={ _t("Search names and descriptions") }
|
||||||
onSearch={setQuery}
|
onSearch={setQuery}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
initialValue={initialText}
|
initialValue={initialText}
|
||||||
|
|
|
@ -64,6 +64,9 @@ import {BetaPill} from "../views/beta/BetaCard";
|
||||||
import {USER_LABS_TAB} from "../views/dialogs/UserSettingsDialog";
|
import {USER_LABS_TAB} from "../views/dialogs/UserSettingsDialog";
|
||||||
import SettingsStore from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
import dis from "../../dispatcher/dispatcher";
|
import dis from "../../dispatcher/dispatcher";
|
||||||
|
import Modal from "../../Modal";
|
||||||
|
import BetaFeedbackDialog from "../views/dialogs/BetaFeedbackDialog";
|
||||||
|
import SdkConfig from "../../SdkConfig";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
space: Room;
|
space: Room;
|
||||||
|
@ -89,6 +92,26 @@ enum Phase {
|
||||||
PrivateExistingRooms,
|
PrivateExistingRooms,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: Temporary for the Spaces Beta only
|
||||||
|
export const SpaceFeedbackPrompt = ({ onClick }: { onClick?: () => void }) => {
|
||||||
|
if (!SdkConfig.get().bug_report_endpoint_url) return null;
|
||||||
|
|
||||||
|
return <div className="mx_SpaceFeedbackPrompt">
|
||||||
|
<hr />
|
||||||
|
<div>
|
||||||
|
<span className="mx_SpaceFeedbackPrompt_text">{ _t("Spaces are a beta feature.") }</span>
|
||||||
|
<AccessibleButton kind="link" onClick={() => {
|
||||||
|
if (onClick) onClick();
|
||||||
|
Modal.createTrackedDialog("Beta Feedback", "feature_spaces", BetaFeedbackDialog, {
|
||||||
|
featureId: "feature_spaces",
|
||||||
|
});
|
||||||
|
}}>
|
||||||
|
{ _t("Feedback") }
|
||||||
|
</AccessibleButton>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
};
|
||||||
|
|
||||||
const RoomMemberCount = ({ room, children }) => {
|
const RoomMemberCount = ({ room, children }) => {
|
||||||
const members = useRoomMembers(room);
|
const members = useRoomMembers(room);
|
||||||
const count = members.length;
|
const count = members.length;
|
||||||
|
@ -398,6 +421,7 @@ const SpaceLanding = ({ space }) => {
|
||||||
<div className="mx_SpaceRoomView_landing_topic">
|
<div className="mx_SpaceRoomView_landing_topic">
|
||||||
<RoomTopic room={space} />
|
<RoomTopic room={space} />
|
||||||
</div>
|
</div>
|
||||||
|
<SpaceFeedbackPrompt />
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<SpaceHierarchy
|
<SpaceHierarchy
|
||||||
|
@ -487,6 +511,7 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
|
||||||
value={buttonLabel}
|
value={buttonLabel}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<SpaceFeedbackPrompt />
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -555,6 +580,7 @@ const SpaceAddExistingRooms = ({ space, onFinished }) => {
|
||||||
{ buttonLabel }
|
{ buttonLabel }
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</div>
|
</div>
|
||||||
|
<SpaceFeedbackPrompt />
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -574,6 +600,7 @@ const SpaceSetupPublicShare = ({ justCreatedOpts, space, onFinished }) => {
|
||||||
{ _t("Go to my first room") }
|
{ _t("Go to my first room") }
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</div>
|
</div>
|
||||||
|
<SpaceFeedbackPrompt />
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -600,6 +627,7 @@ const SpaceSetupPrivateScope = ({ space, justCreatedOpts, onFinished }) => {
|
||||||
<h3>{ _t("Me and my teammates") }</h3>
|
<h3>{ _t("Me and my teammates") }</h3>
|
||||||
<div>{ _t("A private space for you and your teammates") }</div>
|
<div>{ _t("A private space for you and your teammates") }</div>
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
<SpaceFeedbackPrompt />
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -721,6 +749,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
|
||||||
value={buttonLabel}
|
value={buttonLabel}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<SpaceFeedbackPrompt />
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,9 @@ import AccessibleButton from "../elements/AccessibleButton";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||||
import TextWithTooltip from "../elements/TextWithTooltip";
|
import TextWithTooltip from "../elements/TextWithTooltip";
|
||||||
|
import Modal from "../../../Modal";
|
||||||
|
import BetaFeedbackDialog from "../dialogs/BetaFeedbackDialog";
|
||||||
|
import SdkConfig from "../../../SdkConfig";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
title?: string;
|
title?: string;
|
||||||
|
@ -63,9 +66,21 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => {
|
||||||
const info = SettingsStore.getBetaInfo(featureId);
|
const info = SettingsStore.getBetaInfo(featureId);
|
||||||
if (!info) return null; // Beta is invalid/disabled
|
if (!info) return null; // Beta is invalid/disabled
|
||||||
|
|
||||||
const { title, caption, disclaimer, image } = info;
|
const { title, caption, disclaimer, image, feedbackLabel, feedbackSubheading } = info;
|
||||||
const value = SettingsStore.getValue(featureId);
|
const value = SettingsStore.getValue(featureId);
|
||||||
|
|
||||||
|
let feedbackButton;
|
||||||
|
if (value && feedbackLabel && feedbackSubheading && SdkConfig.get().bug_report_endpoint_url) {
|
||||||
|
feedbackButton = <AccessibleButton
|
||||||
|
onClick={() => {
|
||||||
|
Modal.createTrackedDialog("Beta Feedback", featureId, BetaFeedbackDialog, { featureId });
|
||||||
|
}}
|
||||||
|
kind="primary"
|
||||||
|
>
|
||||||
|
{ _t("Feedback") }
|
||||||
|
</AccessibleButton>;
|
||||||
|
}
|
||||||
|
|
||||||
return <div className="mx_BetaCard">
|
return <div className="mx_BetaCard">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="mx_BetaCard_title">
|
<h3 className="mx_BetaCard_title">
|
||||||
|
@ -73,12 +88,15 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => {
|
||||||
<BetaPill />
|
<BetaPill />
|
||||||
</h3>
|
</h3>
|
||||||
<span className="mx_BetaCard_caption">{ _t(caption) }</span>
|
<span className="mx_BetaCard_caption">{ _t(caption) }</span>
|
||||||
<AccessibleButton
|
<div>
|
||||||
onClick={() => SettingsStore.setValue(featureId, null, SettingLevel.DEVICE, !value)}
|
{ feedbackButton }
|
||||||
kind="primary"
|
<AccessibleButton
|
||||||
>
|
onClick={() => SettingsStore.setValue(featureId, null, SettingLevel.DEVICE, !value)}
|
||||||
{ value ? _t("Leave the beta") : _t("Join the beta") }
|
kind={feedbackButton ? "primary_outline" : "primary"}
|
||||||
</AccessibleButton>
|
>
|
||||||
|
{ value ? _t("Leave the beta") : _t("Join the beta") }
|
||||||
|
</AccessibleButton>
|
||||||
|
</div>
|
||||||
{ disclaimer && <div className="mx_BetaCard_disclaimer">
|
{ disclaimer && <div className="mx_BetaCard_disclaimer">
|
||||||
{ disclaimer(value) }
|
{ disclaimer(value) }
|
||||||
</div> }
|
</div> }
|
||||||
|
|
|
@ -36,6 +36,7 @@ import StyledCheckbox from "../elements/StyledCheckbox";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm";
|
import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm";
|
||||||
import ProgressBar from "../elements/ProgressBar";
|
import ProgressBar from "../elements/ProgressBar";
|
||||||
|
import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView";
|
||||||
|
|
||||||
interface IProps extends IDialogProps {
|
interface IProps extends IDialogProps {
|
||||||
matrixClient: MatrixClient;
|
matrixClient: MatrixClient;
|
||||||
|
@ -307,6 +308,7 @@ const AddExistingToSpaceDialog: React.FC<IProps> = ({ matrixClient: cli, space,
|
||||||
<div className="mx_AddExistingToSpaceDialog_footer">
|
<div className="mx_AddExistingToSpaceDialog_footer">
|
||||||
{ footer }
|
{ footer }
|
||||||
</div>
|
</div>
|
||||||
|
<SpaceFeedbackPrompt onClick={() => onFinished(false)} />
|
||||||
</BaseDialog>;
|
</BaseDialog>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
105
src/components/views/dialogs/BetaFeedbackDialog.tsx
Normal file
105
src/components/views/dialogs/BetaFeedbackDialog.tsx
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 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 React, {useState} from "react";
|
||||||
|
|
||||||
|
import QuestionDialog from './QuestionDialog';
|
||||||
|
import { _t } from '../../../languageHandler';
|
||||||
|
import Field from "../elements/Field";
|
||||||
|
import SdkConfig from "../../../SdkConfig";
|
||||||
|
import {IDialogProps} from "./IDialogProps";
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
import {submitFeedback} from "../../../rageshake/submit-rageshake";
|
||||||
|
import StyledCheckbox from "../elements/StyledCheckbox";
|
||||||
|
import Modal from "../../../Modal";
|
||||||
|
import InfoDialog from "./InfoDialog";
|
||||||
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
|
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||||
|
import {Action} from "../../../dispatcher/actions";
|
||||||
|
import {USER_LABS_TAB} from "./UserSettingsDialog";
|
||||||
|
|
||||||
|
interface IProps extends IDialogProps {
|
||||||
|
featureId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BetaFeedbackDialog: React.FC<IProps> = ({featureId, onFinished}) => {
|
||||||
|
const info = SettingsStore.getBetaInfo(featureId);
|
||||||
|
|
||||||
|
const [comment, setComment] = useState("");
|
||||||
|
const [canContact, setCanContact] = useState(false);
|
||||||
|
|
||||||
|
const sendFeedback = async (ok: boolean) => {
|
||||||
|
if (!ok) return onFinished(false);
|
||||||
|
|
||||||
|
submitFeedback(SdkConfig.get().bug_report_endpoint_url, info.feedbackLabel, comment, canContact);
|
||||||
|
onFinished(true);
|
||||||
|
|
||||||
|
Modal.createTrackedDialog("Beta Dialog Sent", featureId, InfoDialog, {
|
||||||
|
title: _t("Beta feedback"),
|
||||||
|
description: _t("Thank you for your feedback, we really appreciate it."),
|
||||||
|
button: _t("Done"),
|
||||||
|
hasCloseButton: false,
|
||||||
|
fixedWidth: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (<QuestionDialog
|
||||||
|
className="mx_BetaFeedbackDialog"
|
||||||
|
hasCancelButton={true}
|
||||||
|
title={_t("Beta feedback")}
|
||||||
|
description={<React.Fragment>
|
||||||
|
<div className="mx_BetaFeedbackDialog_subheading">
|
||||||
|
{ _t(info.feedbackSubheading) }
|
||||||
|
|
||||||
|
{ _t("Your platform and username will be noted to help us use your feedback as much as we can.")}
|
||||||
|
|
||||||
|
<AccessibleButton kind="link" onClick={() => {
|
||||||
|
onFinished(false);
|
||||||
|
defaultDispatcher.dispatch({
|
||||||
|
action: Action.ViewUserSettings,
|
||||||
|
initialTabId: USER_LABS_TAB,
|
||||||
|
});
|
||||||
|
}}>
|
||||||
|
{ _t("To leave the beta, visit your settings.") }
|
||||||
|
</AccessibleButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Field
|
||||||
|
id="feedbackComment"
|
||||||
|
label={_t("Feedback")}
|
||||||
|
type="text"
|
||||||
|
autoComplete="off"
|
||||||
|
value={comment}
|
||||||
|
element="textarea"
|
||||||
|
onChange={(ev) => {
|
||||||
|
setComment(ev.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<StyledCheckbox
|
||||||
|
checked={canContact}
|
||||||
|
onClick={e => setCanContact((e.target as HTMLInputElement).checked)}
|
||||||
|
>
|
||||||
|
{ _t("You may contact me if you have any follow up questions") }
|
||||||
|
</StyledCheckbox>
|
||||||
|
</React.Fragment>}
|
||||||
|
button={_t("Send feedback")}
|
||||||
|
buttonDisabled={!comment}
|
||||||
|
onFinished={sendFeedback}
|
||||||
|
/>);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BetaFeedbackDialog;
|
|
@ -32,6 +32,7 @@ import Modal from "../../../Modal";
|
||||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||||
import {allSettled} from "../../../utils/promise";
|
import {allSettled} from "../../../utils/promise";
|
||||||
import {useDispatcher} from "../../../hooks/useDispatcher";
|
import {useDispatcher} from "../../../hooks/useDispatcher";
|
||||||
|
import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView";
|
||||||
|
|
||||||
interface IProps extends IDialogProps {
|
interface IProps extends IDialogProps {
|
||||||
matrixClient: MatrixClient;
|
matrixClient: MatrixClient;
|
||||||
|
@ -111,6 +112,8 @@ const SpaceSettingsDialog: React.FC<IProps> = ({ matrixClient: cli, space, onFin
|
||||||
|
|
||||||
{ error && <div className="mx_SpaceRoomView_errorText">{ error }</div> }
|
{ error && <div className="mx_SpaceRoomView_errorText">{ error }</div> }
|
||||||
|
|
||||||
|
<SpaceFeedbackPrompt onClick={() => onFinished(false)} />
|
||||||
|
|
||||||
<SpaceBasicSettings
|
<SpaceBasicSettings
|
||||||
avatarUrl={avatarUrlForRoom(space, 80, 80, "crop")}
|
avatarUrl={avatarUrlForRoom(space, 80, 80, "crop")}
|
||||||
avatarDisabled={!canSetAvatar}
|
avatarDisabled={!canSetAvatar}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import {Action} from "../../../dispatcher/actions";
|
||||||
import {USER_LABS_TAB} from "../dialogs/UserSettingsDialog";
|
import {USER_LABS_TAB} from "../dialogs/UserSettingsDialog";
|
||||||
import Field from "../elements/Field";
|
import Field from "../elements/Field";
|
||||||
import withValidation from "../elements/Validation";
|
import withValidation from "../elements/Validation";
|
||||||
|
import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView";
|
||||||
|
|
||||||
const SpaceCreateMenuType = ({ title, description, className, onClick }) => {
|
const SpaceCreateMenuType = ({ title, description, className, onClick }) => {
|
||||||
return (
|
return (
|
||||||
|
@ -152,6 +153,8 @@ const SpaceCreateMenu = ({ onFinished }) => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<p>{ _t("You can change this later") }</p>
|
<p>{ _t("You can change this later") }</p>
|
||||||
|
|
||||||
|
<SpaceFeedbackPrompt onClick={onFinished} />
|
||||||
</React.Fragment>;
|
</React.Fragment>;
|
||||||
} else {
|
} else {
|
||||||
body = <React.Fragment>
|
body = <React.Fragment>
|
||||||
|
|
|
@ -787,11 +787,12 @@
|
||||||
"Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.",
|
"Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.",
|
||||||
"Spaces": "Spaces",
|
"Spaces": "Spaces",
|
||||||
"Spaces are a new way to group rooms and people.": "Spaces are a new way to group rooms and people.",
|
"Spaces are a new way to group rooms and people.": "Spaces are a new way to group rooms and people.",
|
||||||
"%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.",
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.",
|
||||||
"Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta available for web, desktop and Android. Thank you for trying the beta.",
|
"Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta available for web, desktop and Android. Thank you for trying the beta.",
|
||||||
"%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.",
|
"%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.",
|
||||||
"You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "You can leave the beta any time from settings or tapping on a beta badge, like the one above.",
|
"You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "You can leave the beta any time from settings or tapping on a beta badge, like the one above.",
|
||||||
"Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.",
|
"Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.",
|
||||||
|
"You’re using an early version of Spaces, your feedback will really help inform the next versions.": "You’re using an early version of Spaces, your feedback will really help inform the next versions.",
|
||||||
"Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode",
|
"Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode",
|
||||||
"Send and receive voice messages": "Send and receive voice messages",
|
"Send and receive voice messages": "Send and receive voice messages",
|
||||||
"Render LaTeX maths in messages": "Render LaTeX maths in messages",
|
"Render LaTeX maths in messages": "Render LaTeX maths in messages",
|
||||||
|
@ -2063,6 +2064,13 @@
|
||||||
"Invite anyway and never warn me again": "Invite anyway and never warn me again",
|
"Invite anyway and never warn me again": "Invite anyway and never warn me again",
|
||||||
"Invite anyway": "Invite anyway",
|
"Invite anyway": "Invite anyway",
|
||||||
"Close dialog": "Close dialog",
|
"Close dialog": "Close dialog",
|
||||||
|
"Beta feedback": "Beta feedback",
|
||||||
|
"Thank you for your feedback, we really appreciate it.": "Thank you for your feedback, we really appreciate it.",
|
||||||
|
"Your platform and username will be noted to help us use your feedback as much as we can.": "Your platform and username will be noted to help us use your feedback as much as we can.",
|
||||||
|
"To leave the beta, visit your settings.": "To leave the beta, visit your settings.",
|
||||||
|
"Feedback": "Feedback",
|
||||||
|
"You may contact me if you have any follow up questions": "You may contact me if you have any follow up questions",
|
||||||
|
"Send feedback": "Send feedback",
|
||||||
"Please tell us what went wrong or, better, create a GitHub issue that describes the problem.": "Please tell us what went wrong or, better, create a GitHub issue that describes the problem.",
|
"Please tell us what went wrong or, better, create a GitHub issue that describes the problem.": "Please tell us what went wrong or, better, create a GitHub issue that describes the problem.",
|
||||||
"Preparing to send logs": "Preparing to send logs",
|
"Preparing to send logs": "Preparing to send logs",
|
||||||
"Logs sent": "Logs sent",
|
"Logs sent": "Logs sent",
|
||||||
|
@ -2193,10 +2201,8 @@
|
||||||
"Comment": "Comment",
|
"Comment": "Comment",
|
||||||
"There are two ways you can provide feedback and help us improve %(brand)s.": "There are two ways you can provide feedback and help us improve %(brand)s.",
|
"There are two ways you can provide feedback and help us improve %(brand)s.": "There are two ways you can provide feedback and help us improve %(brand)s.",
|
||||||
"PRO TIP: If you start a bug, please submit <debugLogsLink>debug logs</debugLogsLink> to help us track down the problem.": "PRO TIP: If you start a bug, please submit <debugLogsLink>debug logs</debugLogsLink> to help us track down the problem.",
|
"PRO TIP: If you start a bug, please submit <debugLogsLink>debug logs</debugLogsLink> to help us track down the problem.": "PRO TIP: If you start a bug, please submit <debugLogsLink>debug logs</debugLogsLink> to help us track down the problem.",
|
||||||
"Feedback": "Feedback",
|
|
||||||
"Report a bug": "Report a bug",
|
"Report a bug": "Report a bug",
|
||||||
"Please view <existingIssuesLink>existing bugs on Github</existingIssuesLink> first. No match? <newIssueLink>Start a new one</newIssueLink>.": "Please view <existingIssuesLink>existing bugs on Github</existingIssuesLink> first. No match? <newIssueLink>Start a new one</newIssueLink>.",
|
"Please view <existingIssuesLink>existing bugs on Github</existingIssuesLink> first. No match? <newIssueLink>Start a new one</newIssueLink>.": "Please view <existingIssuesLink>existing bugs on Github</existingIssuesLink> first. No match? <newIssueLink>Start a new one</newIssueLink>.",
|
||||||
"Send feedback": "Send feedback",
|
|
||||||
"Confirm abort of host creation": "Confirm abort of host creation",
|
"Confirm abort of host creation": "Confirm abort of host creation",
|
||||||
"Are you sure you wish to abort creation of the host? The process cannot be continued.": "Are you sure you wish to abort creation of the host? The process cannot be continued.",
|
"Are you sure you wish to abort creation of the host? The process cannot be continued.": "Are you sure you wish to abort creation of the host? The process cannot be continued.",
|
||||||
"Abort": "Abort",
|
"Abort": "Abort",
|
||||||
|
@ -2680,9 +2686,10 @@
|
||||||
"Mark as suggested": "Mark as suggested",
|
"Mark as suggested": "Mark as suggested",
|
||||||
"No results found": "No results found",
|
"No results found": "No results found",
|
||||||
"You may want to try a different search or check for typos.": "You may want to try a different search or check for typos.",
|
"You may want to try a different search or check for typos.": "You may want to try a different search or check for typos.",
|
||||||
"Search names and description": "Search names and description",
|
"Search names and descriptions": "Search names and descriptions",
|
||||||
"If you can't find the room you're looking for, ask for an invite or <a>create a new room</a>.": "If you can't find the room you're looking for, ask for an invite or <a>create a new room</a>.",
|
"If you can't find the room you're looking for, ask for an invite or <a>create a new room</a>.": "If you can't find the room you're looking for, ask for an invite or <a>create a new room</a>.",
|
||||||
"Create room": "Create room",
|
"Create room": "Create room",
|
||||||
|
"Spaces are a beta feature.": "Spaces are a beta feature.",
|
||||||
"Public space": "Public space",
|
"Public space": "Public space",
|
||||||
"Private space": "Private space",
|
"Private space": "Private space",
|
||||||
"<inviter/> invites you": "<inviter/> invites you",
|
"<inviter/> invites you": "<inviter/> invites you",
|
||||||
|
|
|
@ -28,6 +28,7 @@ import * as rageshake from './rageshake';
|
||||||
// polyfill textencoder if necessary
|
// polyfill textencoder if necessary
|
||||||
import * as TextEncodingUtf8 from 'text-encoding-utf-8';
|
import * as TextEncodingUtf8 from 'text-encoding-utf-8';
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
|
import SdkConfig from "../SdkConfig";
|
||||||
let TextEncoder = window.TextEncoder;
|
let TextEncoder = window.TextEncoder;
|
||||||
if (!TextEncoder) {
|
if (!TextEncoder) {
|
||||||
TextEncoder = TextEncodingUtf8.TextEncoder;
|
TextEncoder = TextEncodingUtf8.TextEncoder;
|
||||||
|
@ -268,6 +269,25 @@ function uint8ToString(buf: Buffer) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function submitFeedback(endpoint: string, label: string, comment: string, canContact = false) {
|
||||||
|
let version = "UNKNOWN";
|
||||||
|
try {
|
||||||
|
version = await PlatformPeg.get().getAppVersion();
|
||||||
|
} catch (err) {} // PlatformPeg already logs this.
|
||||||
|
|
||||||
|
const body = new FormData();
|
||||||
|
body.append("label", label);
|
||||||
|
body.append("text", comment);
|
||||||
|
body.append("can_contact", canContact ? "yes" : "no");
|
||||||
|
|
||||||
|
body.append("app", "element-web");
|
||||||
|
body.append("version", version);
|
||||||
|
body.append("platform", PlatformPeg.get().getHumanReadableName());
|
||||||
|
body.append("user_id", MatrixClientPeg.get()?.getUserId());
|
||||||
|
|
||||||
|
await _submitReport(SdkConfig.get().bug_report_endpoint_url, body, () => {});
|
||||||
|
}
|
||||||
|
|
||||||
function _submitReport(endpoint: string, body: FormData, progressCallback: (string) => void) {
|
function _submitReport(endpoint: string, body: FormData, progressCallback: (string) => void) {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
const req = new XMLHttpRequest();
|
const req = new XMLHttpRequest();
|
||||||
|
|
|
@ -125,6 +125,8 @@ export interface ISetting {
|
||||||
caption: string; // _td
|
caption: string; // _td
|
||||||
disclaimer?: (enabled: boolean) => ReactNode;
|
disclaimer?: (enabled: boolean) => ReactNode;
|
||||||
image: string; // require(...)
|
image: string; // require(...)
|
||||||
|
feedbackSubheading?: string;
|
||||||
|
feedbackLabel?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +144,7 @@ export const SETTINGS: {[setting: string]: ISetting} = {
|
||||||
disclaimer: (enabled) => {
|
disclaimer: (enabled) => {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
return <>
|
return <>
|
||||||
<p>{ _t("%(brand)s will reload with Spaces disabled. " +
|
<p>{ _t("If you leave, %(brand)s will reload with Spaces disabled. " +
|
||||||
"Communities and custom tags will be visible again.", {
|
"Communities and custom tags will be visible again.", {
|
||||||
brand: SdkConfig.get().brand,
|
brand: SdkConfig.get().brand,
|
||||||
}) }</p>
|
}) }</p>
|
||||||
|
@ -162,6 +164,9 @@ export const SETTINGS: {[setting: string]: ISetting} = {
|
||||||
</>;
|
</>;
|
||||||
},
|
},
|
||||||
image: require("../../res/img/betas/spaces.png"),
|
image: require("../../res/img/betas/spaces.png"),
|
||||||
|
feedbackSubheading: _td("You’re using an early version of Spaces, " +
|
||||||
|
"your feedback will really help inform the next versions."),
|
||||||
|
feedbackLabel: "spaces-feedback",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"feature_dnd": {
|
"feature_dnd": {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue