Add feedback mechanism for beta features
This commit is contained in:
parent
6efc162ce9
commit
bf4c8f048f
6 changed files with 131 additions and 15 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,23 @@ 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 +90,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> }
|
||||||
|
|
69
src/components/views/dialogs/BetaFeedbackDialog.tsx
Normal file
69
src/components/views/dialogs/BetaFeedbackDialog.tsx
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
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";
|
||||||
|
|
||||||
|
interface IProps extends IDialogProps {
|
||||||
|
featureId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BetaFeedbackDialog: React.FC<IProps> = ({featureId, onFinished}) => {
|
||||||
|
const info = SettingsStore.getBetaInfo(featureId);
|
||||||
|
|
||||||
|
const [comment, setComment] = useState("");
|
||||||
|
|
||||||
|
const sendFeedback = async (ok: boolean) => {
|
||||||
|
if (!ok) return onFinished(false);
|
||||||
|
|
||||||
|
submitFeedback(SdkConfig.get().bug_report_endpoint_url, info.feedbackLabel, comment);
|
||||||
|
onFinished(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (<QuestionDialog
|
||||||
|
className="mx_FeedbackDialog"
|
||||||
|
hasCancelButton={true}
|
||||||
|
title={_t("Beta feedback")}
|
||||||
|
description={<React.Fragment>
|
||||||
|
{ _t(info.feedbackSubheading) }
|
||||||
|
|
||||||
|
<Field
|
||||||
|
id="feedbackComment"
|
||||||
|
label={_t("Add comment")}
|
||||||
|
placeholder={_t("Comment")}
|
||||||
|
type="text"
|
||||||
|
autoComplete="off"
|
||||||
|
value={comment}
|
||||||
|
element="textarea"
|
||||||
|
onChange={(ev) => {
|
||||||
|
setComment(ev.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</React.Fragment>}
|
||||||
|
button={_t("Send feedback")}
|
||||||
|
buttonDisabled={!comment}
|
||||||
|
onFinished={sendFeedback}
|
||||||
|
/>);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BetaFeedbackDialog;
|
|
@ -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 (in development)": "Send and receive voice messages (in development)",
|
"Send and receive voice messages (in development)": "Send and receive voice messages (in development)",
|
||||||
"Render LaTeX maths in messages": "Render LaTeX maths in messages",
|
"Render LaTeX maths in messages": "Render LaTeX maths in messages",
|
||||||
|
@ -2063,6 +2064,10 @@
|
||||||
"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",
|
||||||
|
"Add comment": "Add comment",
|
||||||
|
"Comment": "Comment",
|
||||||
|
"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",
|
||||||
|
@ -2189,14 +2194,11 @@
|
||||||
"Rate %(brand)s": "Rate %(brand)s",
|
"Rate %(brand)s": "Rate %(brand)s",
|
||||||
"Tell us below how you feel about %(brand)s so far.": "Tell us below how you feel about %(brand)s so far.",
|
"Tell us below how you feel about %(brand)s so far.": "Tell us below how you feel about %(brand)s so far.",
|
||||||
"Please go into as much detail as you like, so we can track down the problem.": "Please go into as much detail as you like, so we can track down the problem.",
|
"Please go into as much detail as you like, so we can track down the problem.": "Please go into as much detail as you like, so we can track down the problem.",
|
||||||
"Add comment": "Add 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",
|
"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",
|
||||||
|
|
|
@ -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,23 @@ function uint8ToString(buf: Buffer) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function submitFeedback(endpoint: string, label: string, comment: string) {
|
||||||
|
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("app", "element-web");
|
||||||
|
body.append("version", version);
|
||||||
|
body.append("platform", PlatformPeg.get().getHumanReadableName());
|
||||||
|
|
||||||
|
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