Add basic structure for (un)subscribing from lists

This commit is contained in:
Travis Ralston 2019-10-31 15:53:18 -06:00
parent b93508728a
commit 39b657ce7c
4 changed files with 166 additions and 14 deletions

View file

@ -18,6 +18,6 @@ limitations under the License.
@mixin mx_Settings_fullWidthField; @mixin mx_Settings_fullWidthField;
} }
.mx_MjolnirUserSettingsTab_personalRule { .mx_MjolnirUserSettingsTab_listItem {
margin-bottom: 2px; margin-bottom: 2px;
} }

View file

@ -18,8 +18,9 @@ import React from 'react';
import {_t} from "../../../../../languageHandler"; import {_t} from "../../../../../languageHandler";
import {Mjolnir} from "../../../../../mjolnir/Mjolnir"; import {Mjolnir} from "../../../../../mjolnir/Mjolnir";
import {ListRule} from "../../../../../mjolnir/ListRule"; import {ListRule} from "../../../../../mjolnir/ListRule";
import {RULE_SERVER, RULE_USER} from "../../../../../mjolnir/BanList"; import {BanList, RULE_SERVER, RULE_USER} from "../../../../../mjolnir/BanList";
import Modal from "../../../../../Modal"; import Modal from "../../../../../Modal";
import MatrixClientPeg from "../../../../../MatrixClientPeg";
const sdk = require("../../../../.."); const sdk = require("../../../../..");
@ -30,6 +31,7 @@ export default class MjolnirUserSettingsTab extends React.Component {
this.state = { this.state = {
busy: false, busy: false,
newPersonalRule: "", newPersonalRule: "",
newList: "",
}; };
} }
@ -37,6 +39,10 @@ export default class MjolnirUserSettingsTab extends React.Component {
this.setState({newPersonalRule: e.target.value}); this.setState({newPersonalRule: e.target.value});
}; };
_onNewListChanged = (e) => {
this.setState({newList: e.target.value});
};
_onAddPersonalRule = async (e) => { _onAddPersonalRule = async (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -55,8 +61,8 @@ export default class MjolnirUserSettingsTab extends React.Component {
console.error(e); console.error(e);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to remove Mjolnir rule', '', ErrorDialog, { Modal.createTrackedDialog('Failed to add Mjolnir rule', '', ErrorDialog, {
title: _t('Error removing ignored user/server'), title: _t('Error adding ignored user/server'),
description: _t('Something went wrong. Please try again or view your console for hints.'), description: _t('Something went wrong. Please try again or view your console for hints.'),
}); });
} finally { } finally {
@ -64,6 +70,28 @@ export default class MjolnirUserSettingsTab extends React.Component {
} }
}; };
_onSubscribeList = async (e) => {
e.preventDefault();
e.stopPropagation();
this.setState({busy: true});
try {
const room = await MatrixClientPeg.get().joinRoom(this.state.newList);
await Mjolnir.sharedInstance().subscribeToList(room.roomId);
this.setState({newList: ""}); // 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 subscribe to Mjolnir list', '', ErrorDialog, {
title: _t('Error subscribing to list'),
description: _t('Please verify the room ID or alias and try again.'),
});
} finally {
this.setState({busy: false});
}
};
async _removePersonalRule(rule: ListRule) { async _removePersonalRule(rule: ListRule) {
this.setState({busy: true}); this.setState({busy: true});
try { try {
@ -82,6 +110,28 @@ export default class MjolnirUserSettingsTab extends React.Component {
} }
} }
async _unsubscribeFromList(list: BanList) {
this.setState({busy: true});
try {
await Mjolnir.sharedInstance().unsubscribeFromList(list.roomId);
await MatrixClientPeg.get().leave(list.roomId);
} catch (e) {
console.error(e);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to unsubscribe from Mjolnir list', '', ErrorDialog, {
title: _t('Error unsubscribing from list'),
description: _t('Please try again or view your console for hints.'),
});
} finally {
this.setState({busy: false});
}
}
_viewListRules(list: BanList) {
// TODO
}
_renderPersonalBanListRules() { _renderPersonalBanListRules() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
@ -92,9 +142,12 @@ export default class MjolnirUserSettingsTab extends React.Component {
const tiles = []; const tiles = [];
for (const rule of rules) { for (const rule of rules) {
tiles.push( tiles.push(
<li key={rule.entity} className="mx_MjolnirUserSettingsTab_personalRule"> <li key={rule.entity} className="mx_MjolnirUserSettingsTab_listItem">
<AccessibleButton kind="danger_sm" onClick={() => this._removePersonalRule(rule)} <AccessibleButton
disabled={this.state.busy}> kind="danger_sm"
onClick={() => this._removePersonalRule(rule)}
disabled={this.state.busy}
>
{_t("Remove")} {_t("Remove")}
</AccessibleButton>&nbsp; </AccessibleButton>&nbsp;
<code>{rule.entity}</code> <code>{rule.entity}</code>
@ -102,9 +155,52 @@ export default class MjolnirUserSettingsTab extends React.Component {
); );
} }
return <div><p>{_t("You are currently ignoring:")}</p> return (
<ul>{tiles}</ul> <div>
</div>; <p>{_t("You are currently ignoring:")}</p>
<ul>{tiles}</ul>
</div>
);
}
_renderSubscribedBanLists() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const personalList = Mjolnir.sharedInstance().getPersonalList();
const lists = Mjolnir.sharedInstance().lists.filter(b => personalList ? personalList.roomId !== b.roomId : true);
if (!lists || lists.length <= 0) return <i>{_t("You are not subscribed to any lists")}</i>;
const tiles = [];
for (const list of lists) {
const room = MatrixClientPeg.get().getRoom(list.roomId);
const name = room ? <span>{room.name} (<code>{list.roomId}</code>)</span> : <code>list.roomId</code>;
tiles.push(
<li key={list.roomId} className="mx_MjolnirUserSettingsTab_listItem">
<AccessibleButton
kind="danger_sm"
onClick={() => this._unsubscribeFromList(list)}
disabled={this.state.busy}
>
{_t("Unsubscribe")}
</AccessibleButton>&nbsp;
<AccessibleButton
kind="primary_sm"
onClick={() => this._viewListRules(list)}
disabled={this.state.busy}
>
{_t("View rules")}
</AccessibleButton>&nbsp;
{name}
</li>,
);
}
return (
<div>
<p>{_t("You are currently subscribed to:")}</p>
<ul>{tiles}</ul>
</div>
);
} }
render() { render() {
@ -155,8 +251,12 @@ export default class MjolnirUserSettingsTab extends React.Component {
value={this.state.newPersonalRule} value={this.state.newPersonalRule}
onChange={this._onPersonalRuleChanged} onChange={this._onPersonalRuleChanged}
/> />
<AccessibleButton type="submit" kind="primary" onClick={this._onAddPersonalRule} <AccessibleButton
disabled={this.state.busy}> type="submit"
kind="primary"
onClick={this._onAddPersonalRule}
disabled={this.state.busy}
>
{_t("Ignore")} {_t("Ignore")}
</AccessibleButton> </AccessibleButton>
</form> </form>
@ -171,7 +271,28 @@ export default class MjolnirUserSettingsTab extends React.Component {
"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.",
)}</span> )}</span>
</div> </div>
<p>TODO</p> <div>
{this._renderSubscribedBanLists()}
</div>
<div>
<form onSubmit={this._onSubscribeList} autoComplete="off">
<Field
id="mx_MjolnirUserSettingsTab_subscriptionAdd"
type="text"
label={_t("Room ID or alias of ban list")}
value={this.state.newList}
onChange={this._onNewListChanged}
/>
<AccessibleButton
type="submit"
kind="primary"
onClick={this._onSubscribeList}
disabled={this.state.busy}
>
{_t("Subscribe")}
</AccessibleButton>
</form>
</div>
</div> </div>
</div> </div>
); );

View file

@ -641,11 +641,20 @@
"click to reveal": "click to reveal", "click to reveal": "click to reveal",
"Labs": "Labs", "Labs": "Labs",
"Ignored/Blocked": "Ignored/Blocked", "Ignored/Blocked": "Ignored/Blocked",
"Error removing ignored user/server": "Error removing ignored user/server", "Error adding ignored user/server": "Error adding ignored user/server",
"Something went wrong. Please try again or view your console for hints.": "Something went wrong. Please try again or view your console for hints.", "Something went wrong. Please try again or view your console for hints.": "Something went wrong. Please try again or view your console for hints.",
"Error subscribing to list": "Error subscribing to list",
"Please verify the room ID or alias and try again.": "Please verify the room ID or alias and try again.",
"Error removing ignored user/server": "Error removing ignored user/server",
"Error unsubscribing from list": "Error unsubscribing from list",
"Please try again or view your console for hints.": "Please try again or view your console for hints.",
"You have not ignored anyone.": "You have not ignored anyone.", "You have not ignored anyone.": "You have not ignored anyone.",
"Remove": "Remove", "Remove": "Remove",
"You are currently ignoring:": "You are currently ignoring:", "You are currently ignoring:": "You are currently ignoring:",
"You are not subscribed to any lists": "You are not subscribed to any lists",
"Unsubscribe": "Unsubscribe",
"View rules": "View rules",
"You are currently subscribed to:": "You are currently subscribed to:",
"Ignored users": "Ignored users", "Ignored users": "Ignored users",
"⚠ These settings are meant for advanced users.": "⚠ These settings are meant for advanced users.", "⚠ These settings are meant for advanced users.": "⚠ These settings are meant for advanced users.",
"Add users and servers you want to ignore here. Use asterisks to have Riot match any characters. For example, <code>@bot:*</code> 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, <code>@bot:*</code> 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, <code>@bot:*</code> 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, <code>@bot:*</code> would ignore all users that have the name 'bot' on any server.",
@ -658,6 +667,8 @@
"Subscribed lists": "Subscribed lists", "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!", "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.", "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.",
"Room ID or alias of ban list": "Room ID or alias of ban list",
"Subscribe": "Subscribe",
"Notifications": "Notifications", "Notifications": "Notifications",
"Start automatically after system login": "Start automatically after system login", "Start automatically after system login": "Start automatically after system login",
"Always show the window menu bar": "Always show the window menu bar", "Always show the window menu bar": "Always show the window menu bar",

View file

@ -33,6 +33,14 @@ export class Mjolnir {
constructor() { constructor() {
} }
get roomIds(): string[] {
return this._roomIds;
}
get lists(): BanList[] {
return this._lists;
}
start() { start() {
this._mjolnirWatchRef = SettingsStore.watchSetting("mjolnirRooms", null, this._onListsChanged.bind(this)); this._mjolnirWatchRef = SettingsStore.watchSetting("mjolnirRooms", null, this._onListsChanged.bind(this));
@ -101,6 +109,18 @@ export class Mjolnir {
return list; return list;
} }
async subscribeToList(roomId: string) {
const roomIds = [...this._roomIds, roomId];
await SettingsStore.setValue("mjolnirRooms", null, SettingLevel.ACCOUNT, roomIds);
this._lists.push(new BanList(roomId));
}
async unsubscribeFromList(roomId: string) {
const roomIds = this._roomIds.filter(r => r !== roomId);
await SettingsStore.setValue("mjolnirRooms", null, SettingLevel.ACCOUNT, roomIds);
this._lists = this._lists.filter(b => b.roomId !== roomId);
}
_onEvent(event) { _onEvent(event) {
if (!MatrixClientPeg.get()) return; if (!MatrixClientPeg.get()) return;
if (!this._roomIds.includes(event.getRoomId())) return; if (!this._roomIds.includes(event.getRoomId())) return;