Apply prettier formatting

This commit is contained in:
Michael Weimann 2022-12-12 12:24:14 +01:00
parent 1cac306093
commit 526645c791
No known key found for this signature in database
GPG key ID: 53F535A266BB9584
1576 changed files with 65385 additions and 62478 deletions

View file

@ -132,16 +132,16 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
};
this.settingWatchers = [
SettingsStore.watchSetting("notificationsEnabled", null, (...[,,,, value]) =>
SettingsStore.watchSetting("notificationsEnabled", null, (...[, , , , value]) =>
this.setState({ desktopNotifications: value as boolean }),
),
SettingsStore.watchSetting("deviceNotificationsEnabled", null, (...[,,,, value]) => {
SettingsStore.watchSetting("deviceNotificationsEnabled", null, (...[, , , , value]) => {
this.setState({ deviceNotificationsEnabled: value as boolean });
}),
SettingsStore.watchSetting("notificationBodyEnabled", null, (...[,,,, value]) =>
SettingsStore.watchSetting("notificationBodyEnabled", null, (...[, , , , value]) =>
this.setState({ desktopShowBody: value as boolean }),
),
SettingsStore.watchSetting("audioNotificationsEnabled", null, (...[,,,, value]) =>
SettingsStore.watchSetting("audioNotificationsEnabled", null, (...[, , , , value]) =>
this.setState({ audioNotifications: value as boolean }),
),
];
@ -162,7 +162,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
}
public componentWillUnmount() {
this.settingWatchers.forEach(watcher => SettingsStore.unwatchSetting(watcher));
this.settingWatchers.forEach((watcher) => SettingsStore.unwatchSetting(watcher));
}
public componentDidUpdate(prevProps: Readonly<IProps>, prevState: Readonly<IState>): void {
@ -173,19 +173,20 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
private async refreshFromServer() {
try {
const newState = (await Promise.all([
this.refreshRules(),
this.refreshPushers(),
this.refreshThreepids(),
])).reduce((p, c) => Object.assign(c, p), {});
const newState = (
await Promise.all([this.refreshRules(), this.refreshPushers(), this.refreshThreepids()])
).reduce((p, c) => Object.assign(c, p), {});
this.setState<keyof Omit<IState,
"deviceNotificationsEnabled" |
"desktopNotifications" |
"desktopShowBody" |
"audioNotifications" |
"clearingNotifications"
>>({
this.setState<
keyof Omit<
IState,
| "deviceNotificationsEnabled"
| "desktopNotifications"
| "desktopShowBody"
| "audioNotifications"
| "clearingNotifications"
>
>({
...newState,
phase: Phase.Ready,
});
@ -251,7 +252,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
const rule: IAnnotatedPushRule = Object.assign(r, { kind });
const category = categories[rule.rule_id] ?? RuleClass.Other;
if (rule.rule_id[0] === '.') {
if (rule.rule_id[0] === ".") {
defaultRules[category].push(rule);
}
}
@ -278,7 +279,8 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
const vectorState = definition.ruleToVectorState(rule);
preparedNewState.vectorPushRules[category].push({
ruleId: rule.rule_id,
rule, vectorState,
rule,
vectorState,
description: _t(definition.description),
});
}
@ -317,8 +319,8 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
private showSaveError() {
Modal.createDialog(ErrorDialog, {
title: _t('Error saving notification preferences'),
description: _t('An error occurred whilst saving your notification preferences.'),
title: _t("Error saving notification preferences"),
description: _t("An error occurred whilst saving your notification preferences."),
});
}
@ -327,7 +329,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
try {
const masterRule = this.state.masterPushRule;
await MatrixClientPeg.get().setPushRuleEnabled('global', masterRule.kind, masterRule.rule_id, !checked);
await MatrixClientPeg.get().setPushRuleEnabled("global", masterRule.kind, masterRule.rule_id, !checked);
await this.refreshFromServer();
} catch (e) {
this.setState({ phase: Phase.Error });
@ -361,7 +363,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
append: true,
});
} else {
const pusher = this.state.pushers.find(p => p.kind === "email" && p.pushkey === email);
const pusher = this.state.pushers.find((p) => p.kind === "email" && p.pushkey === email);
pusher.kind = null; // flag for delete
await MatrixClientPeg.get().setPusher(pusher);
}
@ -397,14 +399,16 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
let enabled: boolean;
let actions: PushRuleAction[];
if (checkedState === VectorState.On) {
if (rule.actions.length !== 1) { // XXX: Magic number
if (rule.actions.length !== 1) {
// XXX: Magic number
actions = PushRuleVectorState.actionsFor(checkedState);
}
if (this.state.vectorKeywordRuleInfo.vectorState === VectorState.Off) {
enabled = true;
}
} else if (checkedState === VectorState.Loud) {
if (rule.actions.length !== 3) { // XXX: Magic number
if (rule.actions.length !== 3) {
// XXX: Magic number
actions = PushRuleVectorState.actionsFor(checkedState);
}
if (this.state.vectorKeywordRuleInfo.vectorState === VectorState.Off) {
@ -415,20 +419,20 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
}
if (actions) {
await cli.setPushRuleActions('global', rule.kind, rule.rule_id, actions);
await cli.setPushRuleActions("global", rule.kind, rule.rule_id, actions);
}
if (enabled !== undefined) {
await cli.setPushRuleEnabled('global', rule.kind, rule.rule_id, enabled);
await cli.setPushRuleEnabled("global", rule.kind, rule.rule_id, enabled);
}
}
} else {
const definition: VectorPushRuleDefinition = VectorPushRulesDefinitions[rule.ruleId];
const actions = definition.vectorStateToActions[checkedState];
if (!actions) {
await cli.setPushRuleEnabled('global', rule.rule.kind, rule.rule.rule_id, false);
await cli.setPushRuleEnabled("global", rule.rule.kind, rule.rule.rule_id, false);
} else {
await cli.setPushRuleActions('global', rule.rule.kind, rule.rule.rule_id, actions);
await cli.setPushRuleEnabled('global', rule.rule.kind, rule.rule.rule_id, true);
await cli.setPushRuleActions("global", rule.rule.kind, rule.rule.rule_id, actions);
await cli.setPushRuleEnabled("global", rule.rule.kind, rule.rule.rule_id, true);
}
}
@ -453,8 +457,8 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
private async setKeywords(keywords: string[], originalRules: IAnnotatedPushRule[]) {
try {
// De-duplicate and remove empties
keywords = Array.from(new Set(keywords)).filter(k => !!k);
const oldKeywords = Array.from(new Set(originalRules.map(r => r.pattern))).filter(k => !!k);
keywords = Array.from(new Set(keywords)).filter((k) => !!k);
const oldKeywords = Array.from(new Set(originalRules.map((r) => r.pattern))).filter((k) => !!k);
// Note: Technically because of the UI interaction (at the time of writing), the diff
// will only ever be +/-1 so we don't really have to worry about efficiently handling
@ -463,8 +467,8 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
const diff = arrayDiff(oldKeywords, keywords);
for (const word of diff.removed) {
for (const rule of originalRules.filter(r => r.pattern === word)) {
await MatrixClientPeg.get().deletePushRule('global', rule.kind, rule.rule_id);
for (const rule of originalRules.filter((r) => r.pattern === word)) {
await MatrixClientPeg.get().deletePushRule("global", rule.kind, rule.rule_id);
}
}
@ -481,12 +485,12 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
}
const kind = PushRuleKind.ContentSpecific;
for (const word of diff.added) {
await MatrixClientPeg.get().addPushRule('global', kind, word, {
await MatrixClientPeg.get().addPushRule("global", kind, word, {
actions: PushRuleVectorState.actionsFor(ruleVectorState),
pattern: word,
});
if (ruleVectorState === VectorState.Off) {
await MatrixClientPeg.get().setPushRuleEnabled('global', kind, word, false);
await MatrixClientPeg.get().setPushRuleEnabled("global", kind, word, false);
}
}
@ -502,99 +506,120 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
const originalRules = objectClone(this.state.vectorKeywordRuleInfo.rules);
// We add the keyword immediately as a sort of local echo effect
this.setState({
phase: Phase.Persisting,
vectorKeywordRuleInfo: {
...this.state.vectorKeywordRuleInfo,
rules: [
...this.state.vectorKeywordRuleInfo.rules,
this.setState(
{
phase: Phase.Persisting,
vectorKeywordRuleInfo: {
...this.state.vectorKeywordRuleInfo,
rules: [
...this.state.vectorKeywordRuleInfo.rules,
// XXX: Horrible assumption that we don't need the remaining fields
{ pattern: keyword } as IAnnotatedPushRule,
],
// XXX: Horrible assumption that we don't need the remaining fields
{ pattern: keyword } as IAnnotatedPushRule,
],
},
},
}, async () => {
await this.setKeywords(this.state.vectorKeywordRuleInfo.rules.map(r => r.pattern), originalRules);
});
async () => {
await this.setKeywords(
this.state.vectorKeywordRuleInfo.rules.map((r) => r.pattern),
originalRules,
);
},
);
};
private onKeywordRemove = (keyword: string) => {
const originalRules = objectClone(this.state.vectorKeywordRuleInfo.rules);
// We remove the keyword immediately as a sort of local echo effect
this.setState({
phase: Phase.Persisting,
vectorKeywordRuleInfo: {
...this.state.vectorKeywordRuleInfo,
rules: this.state.vectorKeywordRuleInfo.rules.filter(r => r.pattern !== keyword),
this.setState(
{
phase: Phase.Persisting,
vectorKeywordRuleInfo: {
...this.state.vectorKeywordRuleInfo,
rules: this.state.vectorKeywordRuleInfo.rules.filter((r) => r.pattern !== keyword),
},
},
}, async () => {
await this.setKeywords(this.state.vectorKeywordRuleInfo.rules.map(r => r.pattern), originalRules);
});
async () => {
await this.setKeywords(
this.state.vectorKeywordRuleInfo.rules.map((r) => r.pattern),
originalRules,
);
},
);
};
private renderTopSection() {
const masterSwitch = <LabelledToggleSwitch
data-testid='notif-master-switch'
value={!this.isInhibited}
label={_t("Enable notifications for this account")}
caption={_t("Turn off to disable notifications on all your devices and sessions")}
onChange={this.onMasterRuleChanged}
disabled={this.state.phase === Phase.Persisting}
/>;
const masterSwitch = (
<LabelledToggleSwitch
data-testid="notif-master-switch"
value={!this.isInhibited}
label={_t("Enable notifications for this account")}
caption={_t("Turn off to disable notifications on all your devices and sessions")}
onChange={this.onMasterRuleChanged}
disabled={this.state.phase === Phase.Persisting}
/>
);
// If all the rules are inhibited, don't show anything.
if (this.isInhibited) {
return masterSwitch;
}
const emailSwitches = (this.state.threepids || []).filter(t => t.medium === ThreepidMedium.Email)
.map(e => <LabelledToggleSwitch
data-testid='notif-email-switch'
key={e.address}
value={this.state.pushers.some(p => p.kind === "email" && p.pushkey === e.address)}
label={_t("Enable email notifications for %(email)s", { email: e.address })}
onChange={this.onEmailNotificationsChanged.bind(this, e.address)}
disabled={this.state.phase === Phase.Persisting}
/>);
return <>
{ masterSwitch }
<LabelledToggleSwitch
data-testid='notif-device-switch'
value={this.state.deviceNotificationsEnabled}
label={_t("Enable notifications for this device")}
onChange={checked => this.updateDeviceNotifications(checked)}
disabled={this.state.phase === Phase.Persisting}
/>
{ this.state.deviceNotificationsEnabled && (<>
const emailSwitches = (this.state.threepids || [])
.filter((t) => t.medium === ThreepidMedium.Email)
.map((e) => (
<LabelledToggleSwitch
data-testid='notif-setting-notificationsEnabled'
value={this.state.desktopNotifications}
onChange={this.onDesktopNotificationsChanged}
label={_t('Enable desktop notifications for this session')}
data-testid="notif-email-switch"
key={e.address}
value={this.state.pushers.some((p) => p.kind === "email" && p.pushkey === e.address)}
label={_t("Enable email notifications for %(email)s", { email: e.address })}
onChange={this.onEmailNotificationsChanged.bind(this, e.address)}
disabled={this.state.phase === Phase.Persisting}
/>
<LabelledToggleSwitch
data-testid='notif-setting-notificationBodyEnabled'
value={this.state.desktopShowBody}
onChange={this.onDesktopShowBodyChanged}
label={_t('Show message in desktop notification')}
disabled={this.state.phase === Phase.Persisting}
/>
<LabelledToggleSwitch
data-testid='notif-setting-audioNotificationsEnabled'
value={this.state.audioNotifications}
onChange={this.onAudioNotificationsChanged}
label={_t('Enable audible notifications for this session')}
disabled={this.state.phase === Phase.Persisting}
/>
</>) }
));
{ emailSwitches }
</>;
return (
<>
{masterSwitch}
<LabelledToggleSwitch
data-testid="notif-device-switch"
value={this.state.deviceNotificationsEnabled}
label={_t("Enable notifications for this device")}
onChange={(checked) => this.updateDeviceNotifications(checked)}
disabled={this.state.phase === Phase.Persisting}
/>
{this.state.deviceNotificationsEnabled && (
<>
<LabelledToggleSwitch
data-testid="notif-setting-notificationsEnabled"
value={this.state.desktopNotifications}
onChange={this.onDesktopNotificationsChanged}
label={_t("Enable desktop notifications for this session")}
disabled={this.state.phase === Phase.Persisting}
/>
<LabelledToggleSwitch
data-testid="notif-setting-notificationBodyEnabled"
value={this.state.desktopShowBody}
onChange={this.onDesktopShowBodyChanged}
label={_t("Show message in desktop notification")}
disabled={this.state.phase === Phase.Persisting}
/>
<LabelledToggleSwitch
data-testid="notif-setting-audioNotificationsEnabled"
value={this.state.audioNotifications}
onChange={this.onAudioNotificationsChanged}
label={_t("Enable audible notifications for this session")}
disabled={this.state.phase === Phase.Persisting}
/>
</>
)}
{emailSwitches}
</>
);
}
private renderCategory(category: RuleClass) {
@ -604,45 +629,55 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
let clearNotifsButton: JSX.Element;
if (
category === RuleClass.VectorOther
&& MatrixClientPeg.get().getRooms().some(r => r.getUnreadNotificationCount() > 0)
category === RuleClass.VectorOther &&
MatrixClientPeg.get()
.getRooms()
.some((r) => r.getUnreadNotificationCount() > 0)
) {
clearNotifsButton = <AccessibleButton
onClick={this.onClearNotificationsClicked}
disabled={this.state.clearingNotifications}
kind='danger'
className='mx_UserNotifSettings_clearNotifsButton'
data-testid="clear-notifications"
>{ _t("Clear notifications") }</AccessibleButton>;
clearNotifsButton = (
<AccessibleButton
onClick={this.onClearNotificationsClicked}
disabled={this.state.clearingNotifications}
kind="danger"
className="mx_UserNotifSettings_clearNotifsButton"
data-testid="clear-notifications"
>
{_t("Clear notifications")}
</AccessibleButton>
);
}
if (category === RuleClass.VectorOther && this.isInhibited) {
// only render the utility buttons (if needed)
if (clearNotifsButton) {
return <div className='mx_UserNotifSettings_floatingSection'>
<div>{ _t("Other") }</div>
{ clearNotifsButton }
</div>;
return (
<div className="mx_UserNotifSettings_floatingSection">
<div>{_t("Other")}</div>
{clearNotifsButton}
</div>
);
}
return null;
}
let keywordComposer: JSX.Element;
if (category === RuleClass.VectorMentions) {
keywordComposer = <TagComposer
tags={this.state.vectorKeywordRuleInfo?.rules.map(r => r.pattern)}
onAdd={this.onKeywordAdd}
onRemove={this.onKeywordRemove}
disabled={this.state.phase === Phase.Persisting}
label={_t("Keyword")}
placeholder={_t("New keyword")}
/>;
keywordComposer = (
<TagComposer
tags={this.state.vectorKeywordRuleInfo?.rules.map((r) => r.pattern)}
onAdd={this.onKeywordAdd}
onRemove={this.onKeywordRemove}
disabled={this.state.phase === Phase.Persisting}
label={_t("Keyword")}
placeholder={_t("New keyword")}
/>
);
}
const VectorStateToLabel = {
[VectorState.On]: _t('On'),
[VectorState.Off]: _t('Off'),
[VectorState.Loud]: _t('Noisy'),
[VectorState.On]: _t("On"),
[VectorState.Off]: _t("Off"),
[VectorState.Loud]: _t("Noisy"),
};
const makeRadio = (r: IVectorPushRule, s: VectorState) => (
@ -656,17 +691,18 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
/>
);
const fieldsetRows = this.state.vectorPushRules[category].map(r =>
const fieldsetRows = this.state.vectorPushRules[category].map((r) => (
<fieldset
key={category + r.ruleId}
data-testid={category + r.ruleId}
className='mx_UserNotifSettings_gridRowContainer'
className="mx_UserNotifSettings_gridRowContainer"
>
<legend className='mx_UserNotifSettings_gridRowLabel'>{ r.description }</legend>
{ makeRadio(r, VectorState.Off) }
{ makeRadio(r, VectorState.On) }
{ makeRadio(r, VectorState.Loud) }
</fieldset>);
<legend className="mx_UserNotifSettings_gridRowLabel">{r.description}</legend>
{makeRadio(r, VectorState.Off)}
{makeRadio(r, VectorState.On)}
{makeRadio(r, VectorState.Loud)}
</fieldset>
));
let sectionName: TranslatedString;
switch (category) {
@ -683,37 +719,43 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
throw new Error("Developer error: Unnamed notifications section: " + category);
}
return <>
<div data-testid={`notif-section-${category}`} className='mx_UserNotifSettings_grid'>
<span className='mx_UserNotifSettings_gridRowLabel mx_UserNotifSettings_gridRowHeading'>{ sectionName }</span>
<span className='mx_UserNotifSettings_gridColumnLabel'>{ VectorStateToLabel[VectorState.Off] }</span>
<span className='mx_UserNotifSettings_gridColumnLabel'>{ VectorStateToLabel[VectorState.On] }</span>
<span className='mx_UserNotifSettings_gridColumnLabel'>{ VectorStateToLabel[VectorState.Loud] }</span>
{ fieldsetRows }
</div>
{ clearNotifsButton }
{ keywordComposer }
</>;
return (
<>
<div data-testid={`notif-section-${category}`} className="mx_UserNotifSettings_grid">
<span className="mx_UserNotifSettings_gridRowLabel mx_UserNotifSettings_gridRowHeading">
{sectionName}
</span>
<span className="mx_UserNotifSettings_gridColumnLabel">{VectorStateToLabel[VectorState.Off]}</span>
<span className="mx_UserNotifSettings_gridColumnLabel">{VectorStateToLabel[VectorState.On]}</span>
<span className="mx_UserNotifSettings_gridColumnLabel">{VectorStateToLabel[VectorState.Loud]}</span>
{fieldsetRows}
</div>
{clearNotifsButton}
{keywordComposer}
</>
);
}
private renderTargets() {
if (this.isInhibited) return null; // no targets if there's no notifications
const rows = this.state.pushers.map(p => <tr key={p.kind+p.pushkey}>
<td>{ p.app_display_name }</td>
<td>{ p.device_display_name }</td>
</tr>);
const rows = this.state.pushers.map((p) => (
<tr key={p.kind + p.pushkey}>
<td>{p.app_display_name}</td>
<td>{p.device_display_name}</td>
</tr>
));
if (!rows.length) return null; // no targets to show
return <div className='mx_UserNotifSettings_floatingSection'>
<div>{ _t("Notification targets") }</div>
<table>
<tbody>
{ rows }
</tbody>
</table>
</div>;
return (
<div className="mx_UserNotifSettings_floatingSection">
<div>{_t("Notification targets")}</div>
<table>
<tbody>{rows}</tbody>
</table>
</div>
);
}
public render() {
@ -721,15 +763,17 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
// Ends up default centered
return <Spinner />;
} else if (this.state.phase === Phase.Error) {
return <p data-testid='error-message'>{ _t("There was an error loading your notification settings.") }</p>;
return <p data-testid="error-message">{_t("There was an error loading your notification settings.")}</p>;
}
return <div className='mx_UserNotifSettings'>
{ this.renderTopSection() }
{ this.renderCategory(RuleClass.VectorGlobal) }
{ this.renderCategory(RuleClass.VectorMentions) }
{ this.renderCategory(RuleClass.VectorOther) }
{ this.renderTargets() }
</div>;
return (
<div className="mx_UserNotifSettings">
{this.renderTopSection()}
{this.renderCategory(RuleClass.VectorGlobal)}
{this.renderCategory(RuleClass.VectorMentions)}
{this.renderCategory(RuleClass.VectorOther)}
{this.renderTargets()}
</div>
);
}
}