diff --git a/res/css/_components.scss b/res/css/_components.scss index 29c4d2c84c..a0e5881201 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -182,6 +182,7 @@ @import "./views/settings/tabs/room/_SecurityRoomSettingsTab.scss"; @import "./views/settings/tabs/user/_GeneralUserSettingsTab.scss"; @import "./views/settings/tabs/user/_HelpUserSettingsTab.scss"; +@import "./views/settings/tabs/user/_MjolnirUserSettingsTab.scss"; @import "./views/settings/tabs/user/_NotificationUserSettingsTab.scss"; @import "./views/settings/tabs/user/_PreferencesUserSettingsTab.scss"; @import "./views/settings/tabs/user/_SecurityUserSettingsTab.scss"; diff --git a/res/css/views/settings/tabs/user/_MjolnirUserSettingsTab.scss b/res/css/views/settings/tabs/user/_MjolnirUserSettingsTab.scss new file mode 100644 index 0000000000..930dbeb440 --- /dev/null +++ b/res/css/views/settings/tabs/user/_MjolnirUserSettingsTab.scss @@ -0,0 +1,23 @@ +/* +Copyright 2019 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_MjolnirUserSettingsTab .mx_Field { + @mixin mx_Settings_fullWidthField; +} + +.mx_MjolnirUserSettingsTab_personalRule { + margin-bottom: 2px; +} diff --git a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js index 02e64c0bc1..97f92bb0b2 100644 --- a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js @@ -16,28 +16,115 @@ limitations under the License. import React from 'react'; import {_t} from "../../../../../languageHandler"; +import {Mjolnir} from "../../../../../mjolnir/Mjolnir"; +import {ListRule} from "../../../../../mjolnir/ListRule"; +import {RULE_SERVER, RULE_USER} from "../../../../../mjolnir/BanList"; +import Modal from "../../../../../Modal"; + const sdk = require("../../../../.."); export default class MjolnirUserSettingsTab extends React.Component { constructor() { super(); + + this.state = { + busy: false, + newPersonalRule: "", + }; + } + + _onPersonalRuleChanged = (e) => { + this.setState({newPersonalRule: e.target.value}); + }; + + _onAddPersonalRule = async (e) => { + e.preventDefault(); + e.stopPropagation(); + + let kind = RULE_SERVER; + if (this.state.newPersonalRule.startsWith("@")) { + kind = RULE_USER; + } + + this.setState({busy: true}); + try { + const list = await Mjolnir.sharedInstance().getOrCreatePersonalList(); + await list.banEntity(kind, this.state.newPersonalRule, _t("Ignored/Blocked")); + this.setState({newPersonalRule: ""}); // this will also cause the new rule to be rendered + } catch (e) { + console.error(e); + + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + Modal.createTrackedDialog('Failed to remove Mjolnir rule', '', ErrorDialog, { + title: _t('Error removing ignored user/server'), + description: _t('Something went wrong. Please try again or view your console for hints.'), + }); + } finally { + this.setState({busy: false}); + } + }; + + async _removePersonalRule(rule: ListRule) { + this.setState({busy: true}); + try { + const list = Mjolnir.sharedInstance().getPersonalList(); + await list.unbanEntity(rule.kind, rule.entity); + } catch (e) { + console.error(e); + + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + Modal.createTrackedDialog('Failed to remove Mjolnir rule', '', ErrorDialog, { + title: _t('Error removing ignored user/server'), + description: _t('Something went wrong. Please try again or view your console for hints.'), + }); + } finally { + this.setState({busy: false}); + } + } + + _renderPersonalBanListRules() { + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + + const list = Mjolnir.sharedInstance().getPersonalList(); + const rules = list ? [...list.userRules, ...list.serverRules] : []; + if (!list || rules.length <= 0) return {_t("You have not ignored anyone.")}; + + const tiles = []; + for (const rule of rules) { + tiles.push( +
{rule.entity}
+ {_t("You are currently ignoring:")}
+@bot:*
" +
"would ignore all users that have the name 'bot' on any server.",
{}, {code: (s) => {s}
},
- )}TODO
+@bot:*
would ignore all users that have the name 'bot' on any server.": "Add users and servers you want to ignore here. Use asterisks to have Riot match any characters. For example, @bot:*
would ignore all users that have the name 'bot' on any server.",
"Ignoring people is done through ban lists which contain rules for who to ban. Subscribing to a ban list means the users/servers blocked by that list will be hidden from you.": "Ignoring people is done through ban lists which contain rules for who to ban. Subscribing to a ban list means the users/servers blocked by that list will be hidden from you.",
"Personal ban list": "Personal ban list",
"Your personal ban list holds all the users/servers you personally don't want to see messages from. After ignoring your first user/server, a new room will show up in your room list named 'My Ban List' - stay in this room to keep the ban list in effect.": "Your personal ban list holds all the users/servers you personally don't want to see messages from. After ignoring your first user/server, a new room will show up in your room list named 'My Ban List' - stay in this room to keep the ban list in effect.",
+ "Server or user ID to ignore": "Server or user ID to ignore",
+ "eg: @bot:* or example.org": "eg: @bot:* or example.org",
+ "Ignore": "Ignore",
"Subscribed lists": "Subscribed lists",
"Subscribing to a ban list will cause you to join it!": "Subscribing to a ban list will cause you to join it!",
"If this isn't what you want, please use a different tool to ignore users.": "If this isn't what you want, please use a different tool to ignore users.",
@@ -776,7 +785,6 @@
"Discovery options will appear once you have added a phone number above.": "Discovery options will appear once you have added a phone number above.",
"Unable to remove contact information": "Unable to remove contact information",
"Remove %(email)s?": "Remove %(email)s?",
- "Remove": "Remove",
"Invalid Email Address": "Invalid Email Address",
"This doesn't appear to be a valid email address": "This doesn't appear to be a valid email address",
"Unable to add email address": "Unable to add email address",
@@ -843,7 +851,6 @@
"You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.",
"Are you sure?": "Are you sure?",
"No devices with registered encryption keys": "No devices with registered encryption keys",
- "Ignore": "Ignore",
"Jump to read receipt": "Jump to read receipt",
"Mention": "Mention",
"Invite": "Invite",
diff --git a/src/mjolnir/BanList.js b/src/mjolnir/BanList.js
index 6ebc0a7e36..026005420a 100644
--- a/src/mjolnir/BanList.js
+++ b/src/mjolnir/BanList.js
@@ -60,17 +60,23 @@ export class BanList {
return this._rules.filter(r => r.kind === RULE_ROOM);
}
- banEntity(kind: string, entity: string, reason: string): Promise