If no bug_report_endpoint_url, hide rageshaking from the App

This commit is contained in:
Michael Telatynski 2020-09-15 15:49:25 +01:00
parent 9a3c30b1f1
commit 6c166f0560
5 changed files with 33 additions and 15 deletions

View file

@ -43,6 +43,7 @@ import { ensureDMExists } from "./createRoom";
import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload"; import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload";
import { Action } from "./dispatcher/actions"; import { Action } from "./dispatcher/actions";
import { EffectiveMembership, getEffectiveMembership, leaveRoomBehaviour } from "./utils/membership"; import { EffectiveMembership, getEffectiveMembership, leaveRoomBehaviour } from "./utils/membership";
import SdkConfig from "./SdkConfig";
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816 // XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
interface HTMLInputEvent extends Event { interface HTMLInputEvent extends Event {
@ -87,6 +88,7 @@ interface ICommandOpts {
runFn?: RunFn; runFn?: RunFn;
category: string; category: string;
hideCompletionAfterSpace?: boolean; hideCompletionAfterSpace?: boolean;
isEnabled?(): boolean;
} }
export class Command { export class Command {
@ -97,6 +99,7 @@ export class Command {
runFn: undefined | RunFn; runFn: undefined | RunFn;
category: string; category: string;
hideCompletionAfterSpace: boolean; hideCompletionAfterSpace: boolean;
_isEnabled?: () => boolean;
constructor(opts: ICommandOpts) { constructor(opts: ICommandOpts) {
this.command = opts.command; this.command = opts.command;
@ -106,6 +109,7 @@ export class Command {
this.runFn = opts.runFn; this.runFn = opts.runFn;
this.category = opts.category || CommandCategories.other; this.category = opts.category || CommandCategories.other;
this.hideCompletionAfterSpace = opts.hideCompletionAfterSpace || false; this.hideCompletionAfterSpace = opts.hideCompletionAfterSpace || false;
this._isEnabled = opts.isEnabled;
} }
getCommand() { getCommand() {
@ -125,6 +129,10 @@ export class Command {
getUsage() { getUsage() {
return _t('Usage') + ': ' + this.getCommandWithArgs(); return _t('Usage') + ': ' + this.getCommandWithArgs();
} }
isEnabled() {
return this._isEnabled ? this._isEnabled() : true;
}
} }
function reject(error) { function reject(error) {
@ -971,6 +979,7 @@ export const Commands = [
command: "rageshake", command: "rageshake",
aliases: ["bugreport"], aliases: ["bugreport"],
description: _td("Send a bug report with logs"), description: _td("Send a bug report with logs"),
isEnabled: () => !!SdkConfig.get().bug_report_endpoint_url,
args: "<description>", args: "<description>",
runFn: function(roomId, args) { runFn: function(roomId, args) {
return success( return success(
@ -1048,7 +1057,7 @@ Commands.forEach(cmd => {
}); });
}); });
export function parseCommandString(input) { export function parseCommandString(input: string) {
// trim any trailing whitespace, as it can confuse the parser for // trim any trailing whitespace, as it can confuse the parser for
// IRC-style commands // IRC-style commands
input = input.replace(/\s+$/, ''); input = input.replace(/\s+$/, '');
@ -1075,10 +1084,10 @@ export function parseCommandString(input) {
* processing the command, or 'promise' if a request was sent out. * processing the command, or 'promise' if a request was sent out.
* Returns null if the input didn't match a command. * Returns null if the input didn't match a command.
*/ */
export function getCommand(roomId, input) { export function getCommand(roomId: string, input: string) {
const {cmd, args} = parseCommandString(input); const {cmd, args} = parseCommandString(input);
if (CommandMap.has(cmd)) { if (CommandMap.has(cmd) && CommandMap.get(cmd).isEnabled()) {
return () => CommandMap.get(cmd).run(roomId, args, cmd); return () => CommandMap.get(cmd).run(roomId, args, cmd);
} }
} }

View file

@ -47,7 +47,7 @@ export default class CommandProvider extends AutocompleteProvider {
if (command[0] !== command[1]) { if (command[0] !== command[1]) {
// The input looks like a command with arguments, perform exact match // The input looks like a command with arguments, perform exact match
const name = command[1].substr(1); // strip leading `/` const name = command[1].substr(1); // strip leading `/`
if (CommandMap.has(name)) { if (CommandMap.has(name) && CommandMap.get(name).isEnabled()) {
// some commands, namely `me` and `ddg` don't suit having the usage shown whilst typing their arguments // some commands, namely `me` and `ddg` don't suit having the usage shown whilst typing their arguments
if (CommandMap.get(name).hideCompletionAfterSpace) return []; if (CommandMap.get(name).hideCompletionAfterSpace) return [];
matches = [CommandMap.get(name)]; matches = [CommandMap.get(name)];
@ -63,7 +63,7 @@ export default class CommandProvider extends AutocompleteProvider {
} }
return matches.map((result) => { return matches.filter(cmd => cmd.isEnabled()).map((result) => {
let completion = result.getCommand() + ' '; let completion = result.getCommand() + ' ';
const usedAlias = result.aliases.find(alias => `/${alias}` === command[1]); const usedAlias = result.aliases.find(alias => `/${alias}` === command[1]);
// If the command (or an alias) is the same as the one they entered, we don't want to discard their arguments // If the command (or an alias) is the same as the one they entered, we don't want to discard their arguments

View file

@ -24,6 +24,7 @@ export default ({onFinished}) => {
const categories = {}; const categories = {};
Commands.forEach(cmd => { Commands.forEach(cmd => {
if (!cmd.isEnabled()) return;
if (!categories[cmd.category]) { if (!categories[cmd.category]) {
categories[cmd.category] = []; categories[cmd.category] = [];
} }

View file

@ -207,7 +207,8 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
// If the user is entering a command, only consider them typing if it is one which sends a message into the room // If the user is entering a command, only consider them typing if it is one which sends a message into the room
if (isTyping && this.props.model.parts[0].type === "command") { if (isTyping && this.props.model.parts[0].type === "command") {
const {cmd} = parseCommandString(this.props.model.parts[0].text); const {cmd} = parseCommandString(this.props.model.parts[0].text);
if (!CommandMap.has(cmd) || CommandMap.get(cmd).category !== CommandCategories.messages) { const command = CommandMap.get(cmd);
if (!command || !command.isEnabled() || command.category !== CommandCategories.messages) {
isTyping = false; isTyping = false;
} }
} }

View file

@ -204,9 +204,9 @@ export default class HelpUserSettingsTab extends React.Component {
updateButton = <UpdateCheckButton />; updateButton = <UpdateCheckButton />;
} }
return ( let bugReportingSection;
<div className="mx_SettingsTab mx_HelpUserSettingsTab"> if (SdkConfig.get().bug_report_endpoint_url) {
<div className="mx_SettingsTab_heading">{_t("Help & About")}</div> bugReportingSection = (
<div className="mx_SettingsTab_section"> <div className="mx_SettingsTab_section">
<span className='mx_SettingsTab_subheading'>{_t('Bug reporting')}</span> <span className='mx_SettingsTab_subheading'>{_t('Bug reporting')}</span>
<div className='mx_SettingsTab_subsectionText'> <div className='mx_SettingsTab_subsectionText'>
@ -223,11 +223,6 @@ export default class HelpUserSettingsTab extends React.Component {
{_t("Submit debug logs")} {_t("Submit debug logs")}
</AccessibleButton> </AccessibleButton>
</div> </div>
<div className='mx_HelpUserSettingsTab_debugButton'>
<AccessibleButton onClick={this._onClearCacheAndReload} kind='danger'>
{_t("Clear cache and reload")}
</AccessibleButton>
</div>
{ {
_t( "To report a Matrix-related security issue, please read the Matrix.org " + _t( "To report a Matrix-related security issue, please read the Matrix.org " +
"<a>Security Disclosure Policy</a>.", {}, "<a>Security Disclosure Policy</a>.", {},
@ -239,6 +234,13 @@ export default class HelpUserSettingsTab extends React.Component {
} }
</div> </div>
</div> </div>
);
}
return (
<div className="mx_SettingsTab mx_HelpUserSettingsTab">
<div className="mx_SettingsTab_heading">{_t("Help & About")}</div>
{ bugReportingSection }
<div className='mx_SettingsTab_section'> <div className='mx_SettingsTab_section'>
<span className='mx_SettingsTab_subheading'>{_t("FAQ")}</span> <span className='mx_SettingsTab_subheading'>{_t("FAQ")}</span>
<div className='mx_SettingsTab_subsectionText'> <div className='mx_SettingsTab_subsectionText'>
@ -268,6 +270,11 @@ export default class HelpUserSettingsTab extends React.Component {
data-spoiler={MatrixClientPeg.get().getAccessToken()}> data-spoiler={MatrixClientPeg.get().getAccessToken()}>
&lt;{ _t("click to reveal") }&gt; &lt;{ _t("click to reveal") }&gt;
</AccessibleButton> </AccessibleButton>
<div className='mx_HelpUserSettingsTab_debugButton'>
<AccessibleButton onClick={this._onClearCacheAndReload} kind='danger'>
{_t("Clear cache and reload")}
</AccessibleButton>
</div>
</div> </div>
</div> </div>
</div> </div>