matrix-react-sdk
Version:
SDK for matrix.org using React
864 lines (703 loc) • 122 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var sdk = _interopRequireWildcard(require("../../../index"));
var _languageHandler = require("../../../languageHandler");
var _MatrixClientPeg = require("../../../MatrixClientPeg");
var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore"));
var _Modal = _interopRequireDefault(require("../../../Modal"));
var _notifications = require("../../../notifications");
var _SdkConfig = _interopRequireDefault(require("../../../SdkConfig"));
var _LabelledToggleSwitch = _interopRequireDefault(require("../elements/LabelledToggleSwitch"));
var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton"));
var _SettingLevel = require("../../../settings/SettingLevel");
var _UIFeature = require("../../../settings/UIFeature");
var _replaceableComponent = require("../../../utils/replaceableComponent");
var _dec, _class, _class2, _temp;
// TODO: this "view" component still has far too much application logic in it,
// which should be factored out to other files.
// TODO: this component also does a lot of direct poking into this.state, which
// is VERY NAUGHTY.
/**
* Rules that Vector used to set in order to override the actions of default rules.
* These are used to port peoples existing overrides to match the current API.
* These can be removed and forgotten once everyone has moved to the new client.
*/
const LEGACY_RULES = {
"im.vector.rule.contains_display_name": ".m.rule.contains_display_name",
"im.vector.rule.room_one_to_one": ".m.rule.room_one_to_one",
"im.vector.rule.room_message": ".m.rule.message",
"im.vector.rule.invite_for_me": ".m.rule.invite_for_me",
"im.vector.rule.call": ".m.rule.call",
"im.vector.rule.notices": ".m.rule.suppress_notices"
};
function portLegacyActions(actions) {
const decoded = _notifications.NotificationUtils.decodeActions(actions);
if (decoded !== null) {
return _notifications.NotificationUtils.encodeActions(decoded);
} else {
// We don't recognise one of the actions here, so we don't try to
// canonicalise them.
return actions;
}
}
let Notifications = (_dec = (0, _replaceableComponent.replaceableComponent)("views.settings.Notifications"), _dec(_class = (_temp = _class2 = class Notifications extends _react.default.Component {
constructor(...args) {
super(...args);
(0, _defineProperty2.default)(this, "state", {
phase: Notifications.phases.LOADING,
masterPushRule: undefined,
// The master rule ('.m.rule.master')
vectorPushRules: [],
// HS default push rules displayed in Vector UI
vectorContentRules: {
// Keyword push rules displayed in Vector UI
vectorState: _notifications.PushRuleVectorState.ON,
rules: []
},
externalPushRules: [],
// Push rules (except content rule) that have been defined outside Vector UI
externalContentRules: [],
// Keyword push rules that have been defined outside Vector UI
threepids: [] // used for email notifications
});
(0, _defineProperty2.default)(this, "onEnableNotificationsChange", checked => {
const self = this;
this.setState({
phase: Notifications.phases.LOADING
});
_MatrixClientPeg.MatrixClientPeg.get().setPushRuleEnabled('global', self.state.masterPushRule.kind, self.state.masterPushRule.rule_id, !checked).then(function () {
self._refreshFromServer();
});
});
(0, _defineProperty2.default)(this, "onEnableDesktopNotificationsChange", checked => {
_SettingsStore.default.setValue("notificationsEnabled", null, _SettingLevel.SettingLevel.DEVICE, checked).finally(() => {
this.forceUpdate();
});
});
(0, _defineProperty2.default)(this, "onEnableDesktopNotificationBodyChange", checked => {
_SettingsStore.default.setValue("notificationBodyEnabled", null, _SettingLevel.SettingLevel.DEVICE, checked).finally(() => {
this.forceUpdate();
});
});
(0, _defineProperty2.default)(this, "onEnableAudioNotificationsChange", checked => {
_SettingsStore.default.setValue("audioNotificationsEnabled", null, _SettingLevel.SettingLevel.DEVICE, checked).finally(() => {
this.forceUpdate();
});
});
(0, _defineProperty2.default)(this, "onEnableEmailNotificationsChange", (address, checked) => {
let emailPusherPromise;
if (checked) {
const data = {};
data['brand'] = _SdkConfig.default.get().brand;
emailPusherPromise = _MatrixClientPeg.MatrixClientPeg.get().setPusher({
kind: 'email',
app_id: 'm.email',
pushkey: address,
app_display_name: 'Email Notifications',
device_display_name: address,
lang: navigator.language,
data: data,
append: true // We always append for email pushers since we don't want to stop other accounts notifying to the same email address
});
} else {
const emailPusher = this.getEmailPusher(this.state.pushers, address);
emailPusher.kind = null;
emailPusherPromise = _MatrixClientPeg.MatrixClientPeg.get().setPusher(emailPusher);
}
emailPusherPromise.then(() => {
this._refreshFromServer();
}, error => {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
_Modal.default.createTrackedDialog('Error saving email notification preferences', '', ErrorDialog, {
title: (0, _languageHandler._t)('Error saving email notification preferences'),
description: (0, _languageHandler._t)('An error occurred whilst saving your email notification preferences.')
});
});
});
(0, _defineProperty2.default)(this, "onNotifStateButtonClicked", event => {
// FIXME: use .bind() rather than className metadata here surely
const vectorRuleId = event.target.className.split("-")[0];
const newPushRuleVectorState = event.target.className.split("-")[1];
if ("_keywords" === vectorRuleId) {
this._setKeywordsPushRuleVectorState(newPushRuleVectorState);
} else {
const rule = this.getRule(vectorRuleId);
if (rule) {
this._setPushRuleVectorState(rule, newPushRuleVectorState);
}
}
});
(0, _defineProperty2.default)(this, "onKeywordsClicked", event => {
// Compute the keywords list to display
let keywords = [];
for (const i in this.state.vectorContentRules.rules) {
const rule = this.state.vectorContentRules.rules[i];
keywords.push(rule.pattern);
}
if (keywords.length) {
// As keeping the order of per-word push rules hs side is a bit tricky to code,
// display the keywords in alphabetical order to the user
keywords.sort();
keywords = keywords.join(", ");
} else {
keywords = "";
}
const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
_Modal.default.createTrackedDialog('Keywords Dialog', '', TextInputDialog, {
title: (0, _languageHandler._t)('Keywords'),
description: (0, _languageHandler._t)('Enter keywords separated by a comma:'),
button: (0, _languageHandler._t)('OK'),
value: keywords,
onFinished: (shouldLeave, newValue) => {
if (shouldLeave && newValue !== keywords) {
let newKeywords = newValue.split(',');
for (const i in newKeywords) {
newKeywords[i] = newKeywords[i].trim();
} // Remove duplicates and empty
newKeywords = newKeywords.reduce(function (array, keyword) {
if (keyword !== "" && array.indexOf(keyword) < 0) {
array.push(keyword);
}
return array;
}, []);
this._setKeywords(newKeywords);
}
}
});
});
(0, _defineProperty2.default)(this, "_refreshFromServer", () => {
const self = this;
const pushRulesPromise = _MatrixClientPeg.MatrixClientPeg.get().getPushRules().then(self._portRulesToNewAPI).then(function (rulesets) {
/// XXX seriously? wtf is this?
_MatrixClientPeg.MatrixClientPeg.get().pushRules = rulesets; // Get homeserver default rules and triage them by categories
const ruleCategories = {
// The master rule (all notifications disabling)
'.m.rule.master': 'master',
// The default push rules displayed by Vector UI
'.m.rule.contains_display_name': 'vector',
'.m.rule.contains_user_name': 'vector',
'.m.rule.roomnotif': 'vector',
'.m.rule.room_one_to_one': 'vector',
'.m.rule.encrypted_room_one_to_one': 'vector',
'.m.rule.message': 'vector',
'.m.rule.encrypted': 'vector',
'.m.rule.invite_for_me': 'vector',
//'.m.rule.member_event': 'vector',
'.m.rule.call': 'vector',
'.m.rule.suppress_notices': 'vector',
'.m.rule.tombstone': 'vector' // Others go to others
}; // HS default rules
const defaultRules = {
master: [],
vector: {},
others: []
};
for (const kind in rulesets.global) {
for (let i = 0; i < Object.keys(rulesets.global[kind]).length; ++i) {
const r = rulesets.global[kind][i];
const cat = ruleCategories[r.rule_id];
r.kind = kind;
if (r.rule_id[0] === '.') {
if (cat === 'vector') {
defaultRules.vector[r.rule_id] = r;
} else if (cat === 'master') {
defaultRules.master.push(r);
} else {
defaultRules['others'].push(r);
}
}
}
} // Get the master rule if any defined by the hs
if (defaultRules.master.length > 0) {
self.state.masterPushRule = defaultRules.master[0];
} // parse the keyword rules into our state
const contentRules = _notifications.ContentRules.parseContentRules(rulesets);
self.state.vectorContentRules = {
vectorState: contentRules.vectorState,
rules: contentRules.rules
};
self.state.externalContentRules = contentRules.externalRules; // Build the rules displayed in the Vector UI matrix table
self.state.vectorPushRules = [];
self.state.externalPushRules = [];
const vectorRuleIds = ['.m.rule.contains_display_name', '.m.rule.contains_user_name', '.m.rule.roomnotif', '_keywords', '.m.rule.room_one_to_one', '.m.rule.encrypted_room_one_to_one', '.m.rule.message', '.m.rule.encrypted', '.m.rule.invite_for_me', //'im.vector.rule.member_event',
'.m.rule.call', '.m.rule.suppress_notices', '.m.rule.tombstone'];
for (const i in vectorRuleIds) {
const vectorRuleId = vectorRuleIds[i];
if (vectorRuleId === '_keywords') {
// keywords needs a special handling
// For Vector UI, this is a single global push rule but translated in Matrix,
// it corresponds to all content push rules (stored in self.state.vectorContentRule)
self.state.vectorPushRules.push({
"vectorRuleId": "_keywords",
"description": /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)('Messages containing <span>keywords</span>', {}, {
'span': sub => /*#__PURE__*/_react.default.createElement("span", {
className: "mx_UserNotifSettings_keywords",
onClick: self.onKeywordsClicked
}, sub)
})),
"vectorState": self.state.vectorContentRules.vectorState
});
} else {
const ruleDefinition = _notifications.VectorPushRulesDefinitions[vectorRuleId];
const rule = defaultRules.vector[vectorRuleId];
const vectorState = ruleDefinition.ruleToVectorState(rule); //console.log("Refreshing vectorPushRules for " + vectorRuleId +", "+ ruleDefinition.description +", " + rule +", " + vectorState);
self.state.vectorPushRules.push({
"vectorRuleId": vectorRuleId,
"description": (0, _languageHandler._t)(ruleDefinition.description),
// Text from VectorPushRulesDefinitions.js
"rule": rule,
"vectorState": vectorState
}); // if there was a rule which we couldn't parse, add it to the external list
if (rule && !vectorState) {
rule.description = ruleDefinition.description;
self.state.externalPushRules.push(rule);
}
}
} // Build the rules not managed by Vector UI
const otherRulesDescriptions = {
'.m.rule.message': (0, _languageHandler._t)('Notify for all other messages/rooms'),
'.m.rule.fallback': (0, _languageHandler._t)('Notify me for anything else')
};
for (const i in defaultRules.others) {
const rule = defaultRules.others[i];
const ruleDescription = otherRulesDescriptions[rule.rule_id]; // Show enabled default rules that was modified by the user
if (ruleDescription && rule.enabled && !rule.default) {
rule.description = ruleDescription;
self.state.externalPushRules.push(rule);
}
}
});
const pushersPromise = _MatrixClientPeg.MatrixClientPeg.get().getPushers().then(function (resp) {
self.setState({
pushers: resp.pushers
});
});
Promise.all([pushRulesPromise, pushersPromise]).then(function () {
self.setState({
phase: Notifications.phases.DISPLAY
});
}, function (error) {
console.error(error);
self.setState({
phase: Notifications.phases.ERROR
});
}).finally(() => {
// actually explicitly update our state having been deep-manipulating it
self.setState({
masterPushRule: self.state.masterPushRule,
vectorContentRules: self.state.vectorContentRules,
vectorPushRules: self.state.vectorPushRules,
externalContentRules: self.state.externalContentRules,
externalPushRules: self.state.externalPushRules
});
});
_MatrixClientPeg.MatrixClientPeg.get().getThreePids().then(r => this.setState({
threepids: r.threepids
}));
});
(0, _defineProperty2.default)(this, "_onClearNotifications", () => {
const cli = _MatrixClientPeg.MatrixClientPeg.get();
cli.getRooms().forEach(r => {
if (r.getUnreadNotificationCount() > 0) {
const events = r.getLiveTimeline().getEvents();
if (events.length) cli.sendReadReceipt(events.pop());
}
});
});
}
componentDidMount() {
this._refreshFromServer();
}
/*
* Returns the email pusher (pusher of type 'email') for a given
* email address. Email pushers all have the same app ID, so since
* pushers are unique over (app ID, pushkey), there will be at most
* one such pusher.
*/
getEmailPusher(pushers, address) {
if (pushers === undefined) {
return undefined;
}
for (let i = 0; i < pushers.length; ++i) {
if (pushers[i].kind === 'email' && pushers[i].pushkey === address) {
return pushers[i];
}
}
return undefined;
}
getRule(vectorRuleId) {
for (const i in this.state.vectorPushRules) {
const rule = this.state.vectorPushRules[i];
if (rule.vectorRuleId === vectorRuleId) {
return rule;
}
}
}
_setPushRuleVectorState(rule, newPushRuleVectorState) {
if (rule && rule.vectorState !== newPushRuleVectorState) {
this.setState({
phase: Notifications.phases.LOADING
});
const self = this;
const cli = _MatrixClientPeg.MatrixClientPeg.get();
const deferreds = [];
const ruleDefinition = _notifications.VectorPushRulesDefinitions[rule.vectorRuleId];
if (rule.rule) {
const actions = ruleDefinition.vectorStateToActions[newPushRuleVectorState];
if (!actions) {
// The new state corresponds to disabling the rule.
deferreds.push(cli.setPushRuleEnabled('global', rule.rule.kind, rule.rule.rule_id, false));
} else {
// The new state corresponds to enabling the rule and setting specific actions
deferreds.push(this._updatePushRuleActions(rule.rule, actions, true));
}
}
Promise.all(deferreds).then(function () {
self._refreshFromServer();
}, function (error) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to change settings: " + error);
_Modal.default.createTrackedDialog('Failed to change settings', '', ErrorDialog, {
title: (0, _languageHandler._t)('Failed to change settings'),
description: error && error.message ? error.message : (0, _languageHandler._t)('Operation failed'),
onFinished: self._refreshFromServer
});
});
}
}
_setKeywordsPushRuleVectorState(newPushRuleVectorState) {
// Is there really a change?
if (this.state.vectorContentRules.vectorState === newPushRuleVectorState || this.state.vectorContentRules.rules.length === 0) {
return;
}
const self = this;
const cli = _MatrixClientPeg.MatrixClientPeg.get();
this.setState({
phase: Notifications.phases.LOADING
}); // Update all rules in self.state.vectorContentRules
const deferreds = [];
for (const i in this.state.vectorContentRules.rules) {
const rule = this.state.vectorContentRules.rules[i];
let enabled;
let actions;
switch (newPushRuleVectorState) {
case _notifications.PushRuleVectorState.ON:
if (rule.actions.length !== 1) {
actions = _notifications.PushRuleVectorState.actionsFor(_notifications.PushRuleVectorState.ON);
}
if (this.state.vectorContentRules.vectorState === _notifications.PushRuleVectorState.OFF) {
enabled = true;
}
break;
case _notifications.PushRuleVectorState.LOUD:
if (rule.actions.length !== 3) {
actions = _notifications.PushRuleVectorState.actionsFor(_notifications.PushRuleVectorState.LOUD);
}
if (this.state.vectorContentRules.vectorState === _notifications.PushRuleVectorState.OFF) {
enabled = true;
}
break;
case _notifications.PushRuleVectorState.OFF:
enabled = false;
break;
}
if (actions) {
// Note that the workaround in _updatePushRuleActions will automatically
// enable the rule
deferreds.push(this._updatePushRuleActions(rule, actions, enabled));
} else if (enabled != undefined) {
deferreds.push(cli.setPushRuleEnabled('global', rule.kind, rule.rule_id, enabled));
}
}
Promise.all(deferreds).then(function (resps) {
self._refreshFromServer();
}, function (error) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Can't update user notification settings: " + error);
_Modal.default.createTrackedDialog('Can\'t update user notifcation settings', '', ErrorDialog, {
title: (0, _languageHandler._t)('Can\'t update user notification settings'),
description: error && error.message ? error.message : (0, _languageHandler._t)('Operation failed'),
onFinished: self._refreshFromServer
});
});
}
_setKeywords(newKeywords) {
this.setState({
phase: Notifications.phases.LOADING
});
const self = this;
const cli = _MatrixClientPeg.MatrixClientPeg.get();
const removeDeferreds = []; // Remove per-word push rules of keywords that are no more in the list
const vectorContentRulesPatterns = [];
for (const i in self.state.vectorContentRules.rules) {
const rule = self.state.vectorContentRules.rules[i];
vectorContentRulesPatterns.push(rule.pattern);
if (newKeywords.indexOf(rule.pattern) < 0) {
removeDeferreds.push(cli.deletePushRule('global', rule.kind, rule.rule_id));
}
} // If the keyword is part of `externalContentRules`, remove the rule
// before recreating it in the right Vector path
for (const i in self.state.externalContentRules) {
const rule = self.state.externalContentRules[i];
if (newKeywords.indexOf(rule.pattern) >= 0) {
removeDeferreds.push(cli.deletePushRule('global', rule.kind, rule.rule_id));
}
}
const onError = function (error) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to update keywords: " + error);
_Modal.default.createTrackedDialog('Failed to update keywords', '', ErrorDialog, {
title: (0, _languageHandler._t)('Failed to update keywords'),
description: error && error.message ? error.message : (0, _languageHandler._t)('Operation failed'),
onFinished: self._refreshFromServer
});
}; // Then, add the new ones
Promise.all(removeDeferreds).then(function (resps) {
const deferreds = [];
let pushRuleVectorStateKind = self.state.vectorContentRules.vectorState;
if (pushRuleVectorStateKind === _notifications.PushRuleVectorState.OFF) {
// When the current global keywords rule is OFF, we need to look at
// the flavor of rules in 'vectorContentRules' to apply the same actions
// when creating the new rule.
// Thus, this new rule will join the 'vectorContentRules' set.
if (self.state.vectorContentRules.rules.length) {
pushRuleVectorStateKind = _notifications.PushRuleVectorState.contentRuleVectorStateKind(self.state.vectorContentRules.rules[0]);
} else {
// ON is default
pushRuleVectorStateKind = _notifications.PushRuleVectorState.ON;
}
}
for (const i in newKeywords) {
const keyword = newKeywords[i];
if (vectorContentRulesPatterns.indexOf(keyword) < 0) {
if (self.state.vectorContentRules.vectorState !== _notifications.PushRuleVectorState.OFF) {
deferreds.push(cli.addPushRule('global', 'content', keyword, {
actions: _notifications.PushRuleVectorState.actionsFor(pushRuleVectorStateKind),
pattern: keyword
}));
} else {
deferreds.push(self._addDisabledPushRule('global', 'content', keyword, {
actions: _notifications.PushRuleVectorState.actionsFor(pushRuleVectorStateKind),
pattern: keyword
}));
}
}
}
Promise.all(deferreds).then(function (resps) {
self._refreshFromServer();
}, onError);
}, onError);
} // Create a push rule but disabled
_addDisabledPushRule(scope, kind, ruleId, body) {
const cli = _MatrixClientPeg.MatrixClientPeg.get();
return cli.addPushRule(scope, kind, ruleId, body).then(() => cli.setPushRuleEnabled(scope, kind, ruleId, false));
} // Check if any legacy im.vector rules need to be ported to the new API
// for overriding the actions of default rules.
_portRulesToNewAPI(rulesets) {
const needsUpdate = [];
const cli = _MatrixClientPeg.MatrixClientPeg.get();
for (const kind in rulesets.global) {
const ruleset = rulesets.global[kind];
for (let i = 0; i < ruleset.length; ++i) {
const rule = ruleset[i];
if (rule.rule_id in LEGACY_RULES) {
console.log("Porting legacy rule", rule);
needsUpdate.push(function (kind, rule) {
return cli.setPushRuleActions('global', kind, LEGACY_RULES[rule.rule_id], portLegacyActions(rule.actions)).then(() => cli.deletePushRule('global', kind, rule.rule_id)).catch(e => {
console.warn(`Error when porting legacy rule: ${e}`);
});
}(kind, rule));
}
}
}
if (needsUpdate.length > 0) {
// If some of the rules need to be ported then wait for the porting
// to happen and then fetch the rules again.
return Promise.all(needsUpdate).then(() => cli.getPushRules());
} else {
// Otherwise return the rules that we already have.
return rulesets;
}
}
_updatePushRuleActions(rule, actions, enabled) {
const cli = _MatrixClientPeg.MatrixClientPeg.get();
return cli.setPushRuleActions('global', rule.kind, rule.rule_id, actions).then(function () {
// Then, if requested, enabled or disabled the rule
if (undefined != enabled) {
return cli.setPushRuleEnabled('global', rule.kind, rule.rule_id, enabled);
}
});
}
renderNotifRulesTableRow(title, className, pushRuleVectorState) {
return /*#__PURE__*/_react.default.createElement("tr", {
key: className
}, /*#__PURE__*/_react.default.createElement("th", null, title), /*#__PURE__*/_react.default.createElement("th", null, /*#__PURE__*/_react.default.createElement("input", {
className: className + "-" + _notifications.PushRuleVectorState.OFF,
type: "radio",
checked: pushRuleVectorState === _notifications.PushRuleVectorState.OFF,
onChange: this.onNotifStateButtonClicked
})), /*#__PURE__*/_react.default.createElement("th", null, /*#__PURE__*/_react.default.createElement("input", {
className: className + "-" + _notifications.PushRuleVectorState.ON,
type: "radio",
checked: pushRuleVectorState === _notifications.PushRuleVectorState.ON,
onChange: this.onNotifStateButtonClicked
})), /*#__PURE__*/_react.default.createElement("th", null, /*#__PURE__*/_react.default.createElement("input", {
className: className + "-" + _notifications.PushRuleVectorState.LOUD,
type: "radio",
checked: pushRuleVectorState === _notifications.PushRuleVectorState.LOUD,
onChange: this.onNotifStateButtonClicked
})));
}
renderNotifRulesTableRows() {
const rows = [];
for (const i in this.state.vectorPushRules) {
const rule = this.state.vectorPushRules[i];
if (rule.rule === undefined && rule.vectorRuleId.startsWith(".m.")) {
console.warn(`Skipping render of rule ${rule.vectorRuleId} due to no underlying rule`);
continue;
} //console.log("rendering: " + rule.description + ", " + rule.vectorRuleId + ", " + rule.vectorState);
rows.push(this.renderNotifRulesTableRow(rule.description, rule.vectorRuleId, rule.vectorState));
}
return rows;
}
hasEmailPusher(pushers, address) {
if (pushers === undefined) {
return false;
}
for (let i = 0; i < pushers.length; ++i) {
if (pushers[i].kind === 'email' && pushers[i].pushkey === address) {
return true;
}
}
return false;
}
emailNotificationsRow(address, label) {
return /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, {
value: this.hasEmailPusher(this.state.pushers, address),
onChange: this.onEnableEmailNotificationsChange.bind(this, address),
label: label,
key: `emailNotif_${label}`
});
}
render() {
let spinner;
if (this.state.phase === Notifications.phases.LOADING) {
const Loader = sdk.getComponent("elements.Spinner");
spinner = /*#__PURE__*/_react.default.createElement(Loader, null);
}
let masterPushRuleDiv;
if (this.state.masterPushRule) {
masterPushRuleDiv = /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, {
value: !this.state.masterPushRule.enabled,
onChange: this.onEnableNotificationsChange,
label: (0, _languageHandler._t)('Enable notifications for this account')
});
}
let clearNotificationsButton;
if (_MatrixClientPeg.MatrixClientPeg.get().getRooms().some(r => r.getUnreadNotificationCount() > 0)) {
clearNotificationsButton = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: this._onClearNotifications,
kind: "danger"
}, (0, _languageHandler._t)("Clear notifications"));
} // When enabled, the master rule inhibits all existing rules
// So do not show all notification settings
if (this.state.masterPushRule && this.state.masterPushRule.enabled) {
return /*#__PURE__*/_react.default.createElement("div", null, masterPushRuleDiv, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_UserNotifSettings_notifTable"
}, (0, _languageHandler._t)('All notifications are currently disabled for all targets.')), clearNotificationsButton);
}
const emailThreepids = this.state.threepids.filter(tp => tp.medium === "email");
let emailNotificationsRows;
if (emailThreepids.length > 0) {
emailNotificationsRows = emailThreepids.map(threePid => this.emailNotificationsRow(threePid.address, `${(0, _languageHandler._t)('Enable email notifications')} (${threePid.address})`));
} else if (_SettingsStore.default.getValue(_UIFeature.UIFeature.ThirdPartyID)) {
emailNotificationsRows = /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)('Add an email address to configure email notifications'));
} // Build external push rules
const externalRules = [];
for (const i in this.state.externalPushRules) {
const rule = this.state.externalPushRules[i];
externalRules.push( /*#__PURE__*/_react.default.createElement("li", null, (0, _languageHandler._t)(rule.description)));
} // Show keywords not displayed by the vector UI as a single external push rule
let externalKeywords = [];
for (const i in this.state.externalContentRules) {
const rule = this.state.externalContentRules[i];
externalKeywords.push(rule.pattern);
}
if (externalKeywords.length) {
externalKeywords = externalKeywords.join(", ");
externalRules.push( /*#__PURE__*/_react.default.createElement("li", null, (0, _languageHandler._t)('Notifications on the following keywords follow rules which can’t be displayed here:'), externalKeywords));
}
let devicesSection;
if (this.state.pushers === undefined) {
devicesSection = /*#__PURE__*/_react.default.createElement("div", {
className: "error"
}, (0, _languageHandler._t)('Unable to fetch notification target list'));
} else if (this.state.pushers.length === 0) {
devicesSection = null;
} else {
// TODO: It would be great to be able to delete pushers from here too,
// and this wouldn't be hard to add.
const rows = [];
for (let i = 0; i < this.state.pushers.length; ++i) {
rows.push( /*#__PURE__*/_react.default.createElement("tr", {
key: i
}, /*#__PURE__*/_react.default.createElement("td", null, this.state.pushers[i].app_display_name), /*#__PURE__*/_react.default.createElement("td", null, this.state.pushers[i].device_display_name)));
}
devicesSection = /*#__PURE__*/_react.default.createElement("table", {
className: "mx_UserNotifSettings_devicesTable"
}, /*#__PURE__*/_react.default.createElement("tbody", null, rows));
}
if (devicesSection) {
devicesSection = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h3", null, (0, _languageHandler._t)('Notification targets')), devicesSection);
}
let advancedSettings;
if (externalRules.length) {
const brand = _SdkConfig.default.get().brand;
advancedSettings = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h3", null, (0, _languageHandler._t)('Advanced notification settings')), (0, _languageHandler._t)('There are advanced notifications which are not shown here.'), /*#__PURE__*/_react.default.createElement("br", null), (0, _languageHandler._t)('You might have configured them in a client other than %(brand)s. ' + 'You cannot tune them in %(brand)s but they still apply.', {
brand
}), /*#__PURE__*/_react.default.createElement("ul", null, externalRules));
}
return /*#__PURE__*/_react.default.createElement("div", null, masterPushRuleDiv, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_UserNotifSettings_notifTable"
}, spinner, /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, {
value: _SettingsStore.default.getValue("notificationsEnabled"),
onChange: this.onEnableDesktopNotificationsChange,
label: (0, _languageHandler._t)('Enable desktop notifications for this session')
}), /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, {
value: _SettingsStore.default.getValue("notificationBodyEnabled"),
onChange: this.onEnableDesktopNotificationBodyChange,
label: (0, _languageHandler._t)('Show message in desktop notification')
}), /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, {
value: _SettingsStore.default.getValue("audioNotificationsEnabled"),
onChange: this.onEnableAudioNotificationsChange,
label: (0, _languageHandler._t)('Enable audible notifications for this session')
}), emailNotificationsRows, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_UserNotifSettings_pushRulesTableWrapper"
}, /*#__PURE__*/_react.default.createElement("table", {
className: "mx_UserNotifSettings_pushRulesTable"
}, /*#__PURE__*/_react.default.createElement("thead", null, /*#__PURE__*/_react.default.createElement("tr", null, /*#__PURE__*/_react.default.createElement("th", {
width: "55%"
}), /*#__PURE__*/_react.default.createElement("th", {
width: "15%"
}, (0, _languageHandler._t)('Off')), /*#__PURE__*/_react.default.createElement("th", {
width: "15%"
}, (0, _languageHandler._t)('On')), /*#__PURE__*/_react.default.createElement("th", {
width: "15%"
}, (0, _languageHandler._t)('Noisy')))), /*#__PURE__*/_react.default.createElement("tbody", null, this.renderNotifRulesTableRows()))), advancedSettings, devicesSection, clearNotificationsButton));
}
}, (0, _defineProperty2.default)(_class2, "phases", {
LOADING: "LOADING",
// The component is loading or sending data to the hs
DISPLAY: "DISPLAY",
// The component is ready and display data
ERROR: "ERROR" // There was an error
}), _temp)) || _class);
exports.default = Notifications;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL3NldHRpbmdzL05vdGlmaWNhdGlvbnMuanMiXSwibmFtZXMiOlsiTEVHQUNZX1JVTEVTIiwicG9ydExlZ2FjeUFjdGlvbnMiLCJhY3Rpb25zIiwiZGVjb2RlZCIsIk5vdGlmaWNhdGlvblV0aWxzIiwiZGVjb2RlQWN0aW9ucyIsImVuY29kZUFjdGlvbnMiLCJOb3RpZmljYXRpb25zIiwiUmVhY3QiLCJDb21wb25lbnQiLCJwaGFzZSIsInBoYXNlcyIsIkxPQURJTkciLCJtYXN0ZXJQdXNoUnVsZSIsInVuZGVmaW5lZCIsInZlY3RvclB1c2hSdWxlcyIsInZlY3RvckNvbnRlbnRSdWxlcyIsInZlY3RvclN0YXRlIiwiUHVzaFJ1bGVWZWN0b3JTdGF0ZSIsIk9OIiwicnVsZXMiLCJleHRlcm5hbFB1c2hSdWxlcyIsImV4dGVybmFsQ29udGVudFJ1bGVzIiwidGhyZWVwaWRzIiwiY2hlY2tlZCIsInNlbGYiLCJzZXRTdGF0ZSIsIk1hdHJpeENsaWVudFBlZyIsImdldCIsInNldFB1c2hSdWxlRW5hYmxlZCIsInN0YXRlIiwia2luZCIsInJ1bGVfaWQiLCJ0aGVuIiwiX3JlZnJlc2hGcm9tU2VydmVyIiwiU2V0dGluZ3NTdG9yZSIsInNldFZhbHVlIiwiU2V0dGluZ0xldmVsIiwiREVWSUNFIiwiZmluYWxseSIsImZvcmNlVXBkYXRlIiwiYWRkcmVzcyIsImVtYWlsUHVzaGVyUHJvbWlzZSIsImRhdGEiLCJTZGtDb25maWciLCJicmFuZCIsInNldFB1c2hlciIsImFwcF9pZCIsInB1c2hrZXkiLCJhcHBfZGlzcGxheV9uYW1lIiwiZGV2aWNlX2Rpc3BsYXlfbmFtZSIsImxhbmciLCJuYXZpZ2F0b3IiLCJsYW5ndWFnZSIsImFwcGVuZCIsImVtYWlsUHVzaGVyIiwiZ2V0RW1haWxQdXNoZXIiLCJwdXNoZXJzIiwiZXJyb3IiLCJFcnJvckRpYWxvZyIsInNkayIsImdldENvbXBvbmVudCIsIk1vZGFsIiwiY3JlYXRlVHJhY2tlZERpYWxvZyIsInRpdGxlIiwiZGVzY3JpcHRpb24iLCJldmVudCIsInZlY3RvclJ1bGVJZCIsInRhcmdldCIsImNsYXNzTmFtZSIsInNwbGl0IiwibmV3UHVzaFJ1bGVWZWN0b3JTdGF0ZSIsIl9zZXRLZXl3b3Jkc1B1c2hSdWxlVmVjdG9yU3RhdGUiLCJydWxlIiwiZ2V0UnVsZSIsIl9zZXRQdXNoUnVsZVZlY3RvclN0YXRlIiwia2V5d29yZHMiLCJpIiwicHVzaCIsInBhdHRlcm4iLCJsZW5ndGgiLCJzb3J0Iiwiam9pbiIsIlRleHRJbnB1dERpYWxvZyIsImJ1dHRvbiIsInZhbHVlIiwib25GaW5pc2hlZCIsInNob3VsZExlYXZlIiwibmV3VmFsdWUiLCJuZXdLZXl3b3JkcyIsInRyaW0iLCJyZWR1Y2UiLCJhcnJheSIsImtleXdvcmQiLCJpbmRleE9mIiwiX3NldEtleXdvcmRzIiwicHVzaFJ1bGVzUHJvbWlzZSIsImdldFB1c2hSdWxlcyIsIl9wb3J0UnVsZXNUb05ld0FQSSIsInJ1bGVzZXRzIiwicHVzaFJ1bGVzIiwicnVsZUNhdGVnb3JpZXMiLCJkZWZhdWx0UnVsZXMiLCJtYXN0ZXIiLCJ2ZWN0b3IiLCJvdGhlcnMiLCJnbG9iYWwiLCJPYmplY3QiLCJrZXlzIiwiciIsImNhdCIsImNvbnRlbnRSdWxlcyIsIkNvbnRlbnRSdWxlcyIsInBhcnNlQ29udGVudFJ1bGVzIiwiZXh0ZXJuYWxSdWxlcyIsInZlY3RvclJ1bGVJZHMiLCJzdWIiLCJvbktleXdvcmRzQ2xpY2tlZCIsInJ1bGVEZWZpbml0aW9uIiwiVmVjdG9yUHVzaFJ1bGVzRGVmaW5pdGlvbnMiLCJydWxlVG9WZWN0b3JTdGF0ZSIsIm90aGVyUnVsZXNEZXNjcmlwdGlvbnMiLCJydWxlRGVzY3JpcHRpb24iLCJlbmFibGVkIiwiZGVmYXVsdCIsInB1c2hlcnNQcm9taXNlIiwiZ2V0UHVzaGVycyIsInJlc3AiLCJQcm9taXNlIiwiYWxsIiwiRElTUExBWSIsImNvbnNvbGUiLCJFUlJPUiIsImdldFRocmVlUGlkcyIsImNsaSIsImdldFJvb21zIiwiZm9yRWFjaCIsImdldFVucmVhZE5vdGlmaWNhdGlvbkNvdW50IiwiZXZlbnRzIiwiZ2V0TGl2ZVRpbWVsaW5lIiwiZ2V0RXZlbnRzIiwic2VuZFJlYWRSZWNlaXB0IiwicG9wIiwiY29tcG9uZW50RGlkTW91bnQiLCJkZWZlcnJlZHMiLCJ2ZWN0b3JTdGF0ZVRvQWN0aW9ucyIsIl91cGRhdGVQdXNoUnVsZUFjdGlvbnMiLCJtZXNzYWdlIiwiYWN0aW9uc0ZvciIsIk9GRiIsIkxPVUQiLCJyZXNwcyIsInJlbW92ZURlZmVycmVkcyIsInZlY3RvckNvbnRlbnRSdWxlc1BhdHRlcm5zIiwiZGVsZXRlUHVzaFJ1bGUiLCJvbkVycm9yIiwicHVzaFJ1bGVWZWN0b3JTdGF0ZUtpbmQiLCJjb250ZW50UnVsZVZlY3RvclN0YXRlS2luZCIsImFkZFB1c2hSdWxlIiwiX2FkZERpc2FibGVkUHVzaFJ1bGUiLCJzY29wZSIsInJ1bGVJZCIsImJvZHkiLCJuZWVkc1VwZGF0ZSIsInJ1bGVzZXQiLCJsb2ciLCJzZXRQdXNoUnVsZUFjdGlvbnMiLCJjYXRjaCIsImUiLCJ3YXJuIiwicmVuZGVyTm90aWZSdWxlc1RhYmxlUm93IiwicHVzaFJ1bGVWZWN0b3JTdGF0ZSIsIm9uTm90aWZTdGF0ZUJ1dHRvbkNsaWNrZWQiLCJyZW5kZXJOb3RpZlJ1bGVzVGFibGVSb3dzIiwicm93cyIsInN0YXJ0c1dpdGgiLCJoYXNFbWFpbFB1c2hlciIsImVtYWlsTm90aWZpY2F0aW9uc1JvdyIsImxhYmVsIiwib25FbmFibGVFbWFpbE5vdGlmaWNhdGlvbnNDaGFuZ2UiLCJiaW5kIiwicmVuZGVyIiwic3Bpbm5lciIsIkxvYWRlciIsIm1hc3RlclB1c2hSdWxlRGl2Iiwib25FbmFibGVOb3RpZmljYXRpb25zQ2hhbmdlIiwiY2xlYXJOb3RpZmljYXRpb25zQnV0dG9uIiwic29tZSIsIl9vbkNsZWFyTm90aWZpY2F0aW9ucyIsImVtYWlsVGhyZWVwaWRzIiwiZmlsdGVyIiwidHAiLCJtZWRpdW0iLCJlbWFpbE5vdGlmaWNhdGlvbnNSb3dzIiwibWFwIiwidGhyZWVQaWQiLCJnZXRWYWx1ZSIsIlVJRmVhdHVyZSIsIlRoaXJkUGFydHlJRCIsImV4dGVybmFsS2V5d29yZHMiLCJkZXZpY2VzU2VjdGlvbiIsImFkdmFuY2VkU2V0dGluZ3MiLCJvbkVuYWJsZURlc2t0b3BOb3RpZmljYXRpb25zQ2hhbmdlIiwib25FbmFibGVEZXNrdG9wTm90aWZpY2F0aW9uQm9keUNoYW5nZSIsIm9uRW5hYmxlQXVkaW9Ob3RpZmljYXRpb25zQ2hhbmdlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBaUJBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQU1BOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRUE7QUFDQTtBQUVBO0FBQ0E7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU1BLFlBQVksR0FBRztBQUNqQiwwQ0FBd0MsK0JBRHZCO0FBRWpCLG9DQUFrQyx5QkFGakI7QUFHakIsaUNBQStCLGlCQUhkO0FBSWpCLGtDQUFnQyx1QkFKZjtBQUtqQix5QkFBdUIsY0FMTjtBQU1qQiw0QkFBMEI7QUFOVCxDQUFyQjs7QUFTQSxTQUFTQyxpQkFBVCxDQUEyQkMsT0FBM0IsRUFBb0M7QUFDaEMsUUFBTUMsT0FBTyxHQUFHQyxpQ0FBa0JDLGFBQWxCLENBQWdDSCxPQUFoQyxDQUFoQjs7QUFDQSxNQUFJQyxPQUFPLEtBQUssSUFBaEIsRUFBc0I7QUFDbEIsV0FBT0MsaUNBQWtCRSxhQUFsQixDQUFnQ0gsT0FBaEMsQ0FBUDtBQUNILEdBRkQsTUFFTztBQUNIO0FBQ0E7QUFDQSxXQUFPRCxPQUFQO0FBQ0g7QUFDSjs7SUFHb0JLLGEsV0FEcEIsZ0RBQXFCLDhCQUFyQixDLG1DQUFELE1BQ3FCQSxhQURyQixTQUMyQ0MsZUFBTUMsU0FEakQsQ0FDMkQ7QUFBQTtBQUFBO0FBQUEsaURBTy9DO0FBQ0pDLE1BQUFBLEtBQUssRUFBRUgsYUFBYSxDQUFDSSxNQUFkLENBQXFCQyxPQUR4QjtBQUVKQyxNQUFBQSxjQUFjLEVBQUVDLFNBRlo7QUFFdUI7QUFDM0JDLE1BQUFBLGVBQWUsRUFBRSxFQUhiO0FBR2lCO0FBQ3JCQyxNQUFBQSxrQkFBa0IsRUFBRTtBQUFFO0FBQ2xCQyxRQUFBQSxXQUFXLEVBQUVDLG1DQUFvQkMsRUFEakI7QUFFaEJDLFFBQUFBLEtBQUssRUFBRTtBQUZTLE9BSmhCO0FBUUpDLE1BQUFBLGlCQUFpQixFQUFFLEVBUmY7QUFRbUI7QUFDdkJDLE1BQUFBLG9CQUFvQixFQUFFLEVBVGxCO0FBU3NCO0FBQzFCQyxNQUFBQSxTQUFTLEVBQUUsRUFWUCxDQVVXOztBQVZYLEtBUCtDO0FBQUEsdUVBd0J4QkMsT0FBRCxJQUFhO0FBQ3ZDLFlBQU1DLElBQUksR0FBRyxJQUFiO0FBQ0EsV0FBS0MsUUFBTCxDQUFjO0FBQ1ZoQixRQUFBQSxLQUFLLEVBQUVILGFBQWEsQ0FBQ0ksTUFBZCxDQUFxQkM7QUFEbEIsT0FBZDs7QUFJQWUsdUNBQWdCQyxHQUFoQixHQUFzQkMsa0JBQXRCLENBQ0ksUUFESixFQUNjSixJQUFJLENBQUNLLEtBQUwsQ0FBV2pCLGNBQVgsQ0FBMEJrQixJQUR4QyxFQUM4Q04sSUFBSSxDQUFDSyxLQUFMLENBQVdqQixjQUFYLENBQTBCbUIsT0FEeEUsRUFDaUYsQ0FBQ1IsT0FEbEYsRUFFRVMsSUFGRixDQUVPLFlBQVc7QUFDZFIsUUFBQUEsSUFBSSxDQUFDUyxrQkFBTDtBQUNILE9BSkQ7QUFLSCxLQW5Dc0Q7QUFBQSw4RUFxQ2pCVixPQUFELElBQWE7QUFDOUNXLDZCQUFjQyxRQUFkLENBQ0ksc0JBREosRUFDNEIsSUFENUIsRUFFSUMsMkJBQWFDLE1BRmpCLEVBR0lkLE9BSEosRUFJRWUsT0FKRixDQUlVLE1BQU07QUFDWixhQUFLQyxXQUFMO0FBQ0gsT0FORDtBQU9ILEtBN0NzRDtBQUFBLGlGQStDZGhCLE9BQUQsSUFBYTtBQUNqRFcsNkJBQWNDLFFBQWQsQ0FDSSx5QkFESixFQUMrQixJQUQvQixFQUVJQywyQkFBYUMsTUFGakIsRUFHSWQsT0FISixFQUlFZSxPQUpGLENBSVUsTUFBTTtBQUNaLGFBQUtDLFdBQUw7QUFDSCxPQU5EO0FBT0gsS0F2RHNEO0FBQUEsNEVBeURuQmhCLE9BQUQsSUFBYTtBQUM1Q1csNkJBQWNDLFFBQWQsQ0FDSSwyQkFESixFQUNpQyxJQURqQyxFQUVJQywyQkFBYUMsTUFGakIsRUFHSWQsT0FISixFQUlFZSxPQUpGLENBSVUsTUFBTTtBQUNaLGFBQUtDLFdBQUw7QUFDSCxPQU5EO0FBT0gsS0FqRXNEO0FBQUEsNEVBcUZwQixDQUFDQyxPQUFELEVBQVVqQixPQUFWLEtBQXNCO0FBQ3JELFVBQUlrQixrQkFBSjs7QUFDQSxVQUFJbEIsT0FBSixFQUFhO0FBQ1QsY0FBTW1CLElBQUksR0FBRyxFQUFiO0FBQ0FBLFFBQUFBLElBQUksQ0FBQyxPQUFELENBQUosR0FBZ0JDLG1CQUFVaEIsR0FBVixHQUFnQmlCLEtBQWhDO0FBQ0FILFFBQUFBLGtCQUFrQixHQUFHZixpQ0FBZ0JDLEdBQWhCLEdBQXNCa0IsU0FBdEIsQ0FBZ0M7QUFDakRmLFVBQUFBLElBQUksRUFBRSxPQUQyQztBQUVqRGdCLFVBQUFBLE1BQU0sRUFBRSxTQUZ5QztBQUdqREMsVUFBQUEsT0FBTyxFQUFFUCxPQUh3QztBQUlqRFEsVUFBQUEsZ0JBQWdCLEVBQUUscUJBSitCO0FBS2pEQyxVQUFBQSxtQkFBbUIsRUFBRVQsT0FMNEI7QUFNakRVLFVBQUFBLElBQUksRUFBRUMsU0FBUyxDQUFDQyxRQU5pQztBQU9qRFYsVUFBQUEsSUFBSSxFQUFFQSxJQVAyQztBQVFqRFcsVUFBQUEsTUFBTSxFQUFFLElBUnlDLENBUW5DOztBQVJtQyxTQUFoQyxDQUFyQjtBQVVILE9BYkQsTUFhTztBQUNILGNBQU1DLFdBQVcsR0FBRyxLQUFLQyxjQUFMLENBQW9CLEtBQUsxQixLQUFMLENBQVcyQixPQUEvQixFQUF3Q2hCLE9BQXhDLENBQXBCO0FBQ0FjLFFBQUFBLFdBQVcsQ0FBQ3hCLElBQVosR0FBbUIsSUFBbkI7QUFDQVcsUUFBQUEsa0JBQWtCLEdBQUdmLGlDQUFnQkMsR0FBaEIsR0FBc0JrQixTQUF0QixDQUFnQ1MsV0FBaEMsQ0FBckI7QUFDSDs7QUFDRGIsTUFBQUEsa0JBQWtCLENBQUNULElBQW5CLENBQXdCLE1BQU07QUFDMUIsYUFBS0Msa0JBQUw7QUFDSCxPQUZELEVBRUl3QixLQUFELElBQVc7QUFDVixjQUFNQyxXQUFXLEdBQUdDLEdBQUcsQ0FBQ0MsWUFBSixDQUFpQixxQkFBakIsQ0FBcEI7O0FBQ0FDLHVCQUFNQyxtQkFBTixDQUEwQiw2Q0FBMUIsRUFBeUUsRUFBekUsRUFBNkVKLFdBQTdFLEVBQTBGO0FBQ3RGSyxVQUFBQSxLQUFLLEVBQUUseUJBQUcsNkNBQUgsQ0FEK0U7QUFFdEZDLFVBQUFBLFdBQVcsRUFBRSx5QkFBRyxzRUFBSDtBQUZ5RSxTQUExRjtBQUlILE9BUkQ7QUFTSCxLQWxIc0Q7QUFBQSxxRUFvSDFCQyxLQUFELElBQVc7QUFDbkM7QUFDQSxZQUFNQyxZQUFZLEdBQUdELEtBQUssQ0FBQ0UsTUFBTixDQUFhQyxTQUFiLENBQXVCQyxLQUF2QixDQUE2QixHQUE3QixFQUFrQyxDQUFsQyxDQUFyQjtBQUNBLFlBQU1DLHNCQUFzQixHQUFHTCxLQUFLLENBQUNFLE1BQU4sQ0FBYUMsU0FBYixDQUF1QkMsS0FBdkIsQ0FBNkIsR0FBN0IsRUFBa0MsQ0FBbEMsQ0FBL0I7O0FBRUEsVUFBSSxnQkFBZ0JILFlBQXBCLEVBQWtDO0FBQzlCLGFBQUtLLCtCQUFMLENBQXFDRCxzQkFBckM7QUFDSCxPQUZELE1BRU87QUFDSCxjQUFNRSxJQUFJLEdBQUcsS0FBS0MsT0FBTCxDQUFhUCxZQUFiLENBQWI7O0FBQ0EsWUFBSU0sSUFBSixFQUFVO0FBQ04sZUFBS0UsdUJBQUwsQ0FBNkJGLElBQTdCLEVBQW1DRixzQkFBbkM7QUFDSDtBQUNKO0FBQ0osS0FqSXNEO0FBQUEsNkRBbUlsQ0wsS0FBRCxJQUFXO0FBQzNCO0FBQ0EsVUFBSVUsUUFBUSxHQUFHLEVBQWY7O0FBQ0EsV0FBSyxNQUFNQyxDQUFYLElBQWdCLEtBQUsvQyxLQUFMLENBQVdkLGtCQUFYLENBQThCSSxLQUE5QyxFQUFxRDtBQUNqRCxjQUFNcUQsSUFBSSxHQUFHLEtBQUszQyxLQUFMLENBQVdkLGtCQUFYLENBQThCSSxLQUE5QixDQUFvQ3lELENBQXBDLENBQWI7QUFDQUQsUUFBQUEsUUFBUSxDQUFDRSxJQUFULENBQWNMLElBQUksQ0FBQ00sT0FBbkI7QUFDSDs7QUFDRCxVQUFJSCxRQUFRLENBQUNJLE1BQWIsRUFBcUI7QUFDakI7QUFDQTtBQUNBSixRQUFBQSxRQUFRLENBQUNLLElBQVQ7QUFFQUwsUUFBQUEsUUFBUSxHQUFHQSxRQUFRLENBQUNNLElBQVQsQ0FBYyxJQUFkLENBQVg7QUFDSCxPQU5ELE1BTU87QUFDSE4sUUFBQUEsUUFBUSxHQUFHLEVBQVg7QUFDSDs7QUFFRCxZQUFNTyxlQUFlLEdBQUd2QixHQUFHLENBQUNDLFlBQUosQ0FBaUIseUJBQWpCLENBQXhCOztBQUNBQyxxQkFBTUMsbUJBQU4sQ0FBMEIsaUJBQTFCLEVBQTZDLEVBQTdDLEVBQWlEb0IsZUFBakQsRUFBa0U7QUFDOURuQixRQUFBQSxLQUFLLEVBQUUseUJBQUcsVUFBSCxDQUR1RDtBQUU5REMsUUFBQUEsV0FBVyxFQUFFLHlCQUFHLHNDQUFILENBRmlEO0FBRzlEbUIsUUFBQUEsTUFBTSxFQUFFLHlCQUFHLElBQUgsQ0FIc0Q7QUFJOURDLFFBQUFBLEtBQUssRUFBRVQsUUFKdUQ7QUFLOURVLFFBQUFBLFVBQVUsRUFBRSxDQUFDQyxXQUFELEVBQWNDLFFBQWQsS0FBMkI7QUFDbkMsY0FBSUQsV0FBVyxJQUFJQyxRQUFRLEtBQUtaLFFBQWhDLEVBQTBDO0FBQ3RDLGdCQUFJYSxXQUFXLEdBQUdELFFBQVEsQ0FBQ2xCLEtBQVQsQ0FBZSxHQUFmLENBQWxCOztBQUNBLGlCQUFLLE1BQU1PLENBQVgsSUFBZ0JZLFdBQWhCLEVBQTZCO0FBQ3pCQSxjQUFBQSxXQUFXLENBQUNaLENBQUQsQ0FBWCxHQUFpQlksV0FBVyxDQUFDWixDQUFELENBQVgsQ0FBZWEsSUFBZixFQUFqQjtBQUNILGFBSnFDLENBTXRDOzs7QUFDQUQsWUFBQUEsV0FBVyxHQUFHQSxXQUFXLENBQUNFLE1BQVosQ0FBbUIsVUFBU0MsS0FBVCxFQUFnQkMsT0FBaEIsRUFBeUI7QUFDdEQsa0JBQUlBLE9BQU8sS0FBSyxFQUFaLElBQWtCRCxLQUFLLENBQUNFLE9BQU4sQ0FBY0QsT0FBZCxJQUF5QixDQUEvQyxFQUFrRDtBQUM5Q0QsZ0JBQUFBLEtBQUssQ0FBQ2QsSUFBTixDQUFXZSxPQUFYO0FBQ0g7O0FBQ0QscUJBQU9ELEtBQVA7QUFDSCxhQUxhLEVBS1gsRUFMVyxDQUFkOztBQU9BLGlCQUFLRyxZQUFMLENBQWtCTixXQUFsQjtBQUNIO0FBQ0o7QUF0QjZELE9BQWxFO0FBd0JILEtBN0tzRDtBQUFBLDhEQW1hbEMsTUFBTTtBQUN2QixZQUFNaEUsSUFBSSxHQUFHLElBQWI7O0FBQ0EsWUFBTXVFLGdCQUFnQixHQUFHckUsaUNBQWdCQyxHQUFoQixHQUFzQnFFLFlBQXRCLEdBQXFDaEUsSUFBckMsQ0FDckJSLElBQUksQ0FBQ3lFLGtCQURnQixFQUV2QmpFLElBRnVCLENBRWxCLFVBQVNrRSxRQUFULEVBQW1CO0FBQ3RCO0FBQ0F4RSx5Q0FBZ0JDLEdBQWhCLEdBQXNCd0UsU0FBdEIsR0FBa0NELFFBQWxDLENBRnNCLENBSXRCOztBQUNBLGNBQU1FLGNBQWMsR0FBRztBQUNuQjtBQUNBLDRCQUFrQixRQUZDO0FBSW5CO0FBQ0EsMkNBQWlDLFFBTGQ7QUFNbkIsd0NBQThCLFFBTlg7QUFPbkIsK0JBQXFCLFFBUEY7QUFRbkIscUNBQTJCLFFBUlI7QUFTbkIsK0NBQXFDLFFBVGxCO0FBVW5CLDZCQUFtQixRQVZBO0FBV25CLCtCQUFxQixRQVhGO0FBWW5CLG1DQUF5QixRQVpOO0FBYW5CO0FBQ0EsMEJBQWdCLFFBZEc7QUFlbkIsc0NBQTRCLFFBZlQ7QUFnQm5CLCtCQUFxQixRQWhCRixDQWtCbkI7O0FBbEJtQixTQUF2QixDQUxzQixDQTBCdEI7O0FBQ0EsY0FBTUMsWUFBWSxHQUFHO0FBQUNDLFVBQUFBLE1BQU0sRUFBRSxFQUFUO0FBQWFDLFVBQUFBLE1BQU0sRUFBRSxFQUFyQjtBQUF5QkMsVUFBQUEsTUFBTSxFQUFFO0FBQWpDLFNBQXJCOztBQUVBLGFBQUssTUFBTTFFLElBQVgsSUFBbUJvRSxRQUFRLENBQUNPLE1BQTVCLEVBQW9DO0FBQ2hDLGVBQUssSUFBSTdCLENBQUMsR0FBRyxDQUFiLEVBQWdCQSxDQUFDLEdBQUc4QixNQUFNLENBQUNDLElBQVAsQ0FBWVQsUUFBUSxDQUFDTyxNQUFULENBQWdCM0UsSUFBaEIsQ0FBWixFQUFtQ2lELE1BQXZELEVBQStELEVBQUVILENBQWpFLEVBQW9FO0FBQ2hFLGtCQUFNZ0MsQ0FBQyxHQUFHVixRQUFRLENBQUNPLE1BQVQsQ0FBZ0IzRSxJQUFoQixFQUFzQjhDLENBQXRCLENBQVY7QUFDQSxrQkFBTWlDLEdBQUcsR0FBR1QsY0FBYyxDQUFDUSxDQUFDLENBQUM3RSxPQUFILENBQTFCO0FBQ0E2RSxZQUFBQSxDQUFDLENBQUM5RSxJQUFGLEdBQVNBLElBQVQ7O0FBRUEsZ0JBQUk4RSxDQUFDLENBQUM3RSxPQUFGLENBQVUsQ0FBVixNQUFpQixHQUFyQixFQUEwQjtBQUN0QixrQkFBSThFLEdBQUcsS0FBSyxRQUFaLEVBQXNCO0FBQ2xCUixnQkFBQUEsWUFBWSxDQUFDRSxNQUFiLENBQW9CSyxDQUFDLENBQUM3RSxPQUF0QixJQUFpQzZFLENBQWpDO0FBQ0gsZUFGRCxNQUVPLElBQUlDLEdBQUcsS0FBSyxRQUFaLEVBQXNCO0FBQ3pCUixnQkFBQUEsWUFBWSxDQUFDQyxNQUFiLENBQW9CekIsSUFBcEIsQ0FBeUIrQixDQUF6QjtBQUNILGVBRk0sTUFFQTtBQUNIUCxnQkFBQUEsWUFBWSxDQUFDLFFBQUQsQ0FBWixDQUF1QnhCLElBQXZCLENBQTRCK0IsQ0FBNUI7QUFDSDtBQUNKO0FBQ0o7QUFDSixTQTdDcUIsQ0ErQ3RCOzs7QUFDQSxZQUFJUCxZQUFZLENBQUNDLE1BQWIsQ0FBb0J2QixNQUFwQixHQUE2QixDQUFqQyxFQUFvQztBQUNoQ3ZELFVBQUFBLElBQUksQ0FBQ0ssS0FBTCxDQUFXakIsY0FBWCxHQUE0QnlGLFlBQVksQ0FBQ0MsTUFBYixDQUFvQixDQUFwQixDQUE1QjtBQUNILFNBbERxQixDQW9EdEI7OztBQUNBLGNBQU1RLFlBQVksR0FBR0MsNEJBQWFDLGlCQUFiLENBQStCZCxRQUEvQixDQUFyQjs7QUFDQTFFLFFBQUFBLElBQUksQ0FBQ0ssS0FBTCxDQUFXZCxrQkFBWCxHQUFnQztBQUM1QkMsVUFBQUEsV0FBVyxFQUFFOEYsWUFBWSxDQUFDOUYsV0FERTtBQUU1QkcsVUFBQUEsS0FBSyxFQUFFMkYsWUFBWSxDQUFDM0Y7QUFGUSxTQUFoQztBQUlBSyxRQUFBQSxJQUFJLENBQUNLLEtBQUwsQ0FBV1Isb0JBQVgsR0FBa0N5RixZQUFZLENBQUNHLGFBQS9DLENBMURzQixDQTREdEI7O0FBQ0F6RixRQUFBQSxJQUFJLENBQUNLLEtBQUwsQ0FBV2YsZUFBWCxHQUE2QixFQUE3QjtBQUNBVSxRQUFBQSxJQUFJLENBQUNLLEtBQUwsQ0FBV1QsaUJBQVgsR0FBK0IsRUFBL0I7QUFFQSxjQUFNOEYsYUFBYSxHQUFHLENBQ2xCLCtCQURrQixFQUVsQiw0QkFGa0IsRUFHbEIsbUJBSGtCLEVBSWxCLFdBSmtCLEVBS2xCLHlCQUxrQixFQU1sQixtQ0FOa0IsRUFPbEIsaUJBUGtCLEVBUWxCLG1CQVJrQixFQVNsQix1QkFUa0IsRUFVbEI7QUFDQSxzQkFYa0IsRUFZbEIsMEJBWmtCLEVBYWxCLG1CQWJrQixDQUF0Qjs7QUFlQSxhQUFLLE1BQU10QyxDQUFYLElBQWdCc0MsYUFBaEIsRUFBK0I7QUFDM0IsZ0JBQU1oRCxZQUFZLEdBQUdnRCxhQUFhLENBQUN0QyxDQUFELENBQWxDOztBQUVBLGNBQUlWLFlBQVksS0FBSyxXQUFyQixFQUFrQztBQUM5QjtBQUNBO0FBQ0E7QUFDQTFDLFlBQUFBLElBQUksQ0FBQ0ssS0FBTCxDQUFXZixlQUFYLENBQTJCK0QsSUFBM0IsQ0FBZ0M7QUFDNUIsOEJBQWdCLFdBRFk7QUFFNUIsMENBQ0ksMkNBQ00seUJBQUcsMkNBQUgsRUFDRSxFQURGLEVBRUU7QUFBRSx3QkFBU3NDLEdBQUQsaUJBQ047QUFBTSxrQkFBQSxTQUFTLEVBQUMsK0JBQWhCO0FBQWdELGtCQUFBLE9BQU8sRUFBRzNGLElBQUksQ0FBQzRGO0FBQS9ELG1CQUFvRkQsR0FBcEY7QUFESixlQUZGLENBRE4sQ0FId0I7QUFZNUIsNkJBQWUzRixJQUFJLENBQUNLLEtBQUwsQ0FBV2Qsa0JBQVgsQ0FBOEJDO0FBWmpCLGFBQWhDO0FBY0gsV0FsQkQsTUFrQk87QUFDSCxrQkFBTXFHLGNBQWMsR0FBR0MsMENBQTJCcEQsWUFBM0IsQ0FBdkI7QUFDQSxrQkFBTU0sSUFBSSxHQUFHNkIsWUFBWSxDQUFDRSxNQUFiLENBQW9CckMsWUFBcEIsQ0FBYjtBQUVBLGtCQUFNbEQsV0FBVyxHQUFHcUcsY0FBYyxDQUFDRSxpQkFBZixDQUFpQy9DLElBQWpDLENBQXBCLENBSkcsQ0FNSDs7QUFFQWhELFlBQUFBLElBQUksQ0FBQ0ssS0FBTCxDQUFXZixlQUFYLENBQTJCK0QsSUFBM0IsQ0FBZ0M7QUFDNUIsOEJBQWdCWCxZQURZO0FBRTVCLDZCQUFlLHlCQUFHbUQsY0FBYyxDQUFDckQsV0FBbEIsQ0FGYTtBQUVtQjtBQUMvQyxzQkFBUVEsSUFIb0I7QUFJNUIsNkJBQWV4RDtBQUphLGFBQWhDLEVBUkcsQ0FlSDs7QUFDQSxnQkFBSXdELElBQUksSUFBSSxDQUFDeEQsV0FBYixFQUEwQjtBQUN0QndELGNBQUFBLElBQUksQ0FBQ1IsV0FBTCxHQUFtQnFELGNBQWMsQ0FBQ3JELFdBQWxDO0FBQ0F4QyxjQUFBQSxJQUFJLENBQUNLLEtBQUwsQ0FBV1QsaUJBQVgsQ0FBNkJ5RCxJQUE3QixDQUFrQ0wsSUFBbEM7QUFDSDtBQUNKO0FBQ0osU0F6SHFCLENBMkh0Qjs7O0FBQ0EsY0FBTWdELHNCQUFzQixHQUFHO0FBQzNCLDZCQUFtQix5QkFBRyxxQ0FBSCxDQURRO0FBRTNCLDhCQUFvQix5QkFBRyw2QkFBSDtBQUZPLFNBQS9COztBQUtBLGFBQUssTUFBTTVDLENBQVgsSUFBZ0J5QixZQUFZLENBQUNHLE1BQTdCLEVBQXFDO0FBQ2pDLGdCQUFNaEMsSUFBSSxHQUFHNkIsWUFBWSxDQUFDRyxNQUFiLENBQW9CNUIsQ0FBcEIsQ0FBYjtBQUNBLGdCQUFNNkMsZUFBZSxHQUFHRCxzQkFBc0IsQ0FBQ2hELElBQUksQ0FBQ3pDLE9BQU4sQ0FBOUMsQ0FGaUMsQ0FJakM7O0FBQ0EsY0FBSTBGLGVBQWUsSUFBSWpELElBQUksQ0FBQ2tELE9BQXhCLElBQW1DLENBQUNsRCxJQUFJLENBQUNtRCxPQUE3QyxFQUFzRDtBQUNsRG5ELFlBQUFBLElBQUksQ0FBQ1IsV0FBTCxHQUFtQnlELGVBQW5CO0FBQ0FqRyxZQUFBQSxJQUFJLENBQUNLLEtBQUwsQ0FBV1QsaUJBQVgsQ0FBNkJ5RCxJQUE3QixDQUFrQ0wsSUFBbEM7QUFDSDtBQUNKO0FBQ0osT0E3SXdCLENBQXpCOztBQStJQSxZQUFNb0QsY0FBYyxHQUFHbEcsaUNBQWdCQyxHQUFoQixHQU