Migrate Server Limit Bar Banner to a Toast

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
pull/21833/head
Michael Telatynski 2020-05-22 22:27:19 +01:00
parent 5d0040b8b3
commit ccf9e65123
3 changed files with 80 additions and 125 deletions

View File

@ -47,6 +47,10 @@ import {
showToast as showSetPasswordToast,
hideToast as hideSetPasswordToast
} from "../../toasts/SetPasswordToast";
import {
showToast as showServerLimitToast,
hideToast as hideServerLimitToast
} from "../../toasts/ServerLimitToast";
// We need to fetch each pinned message individually (if we don't already have it)
// so each pinned message may trigger a request. Limit the number per room for sanity.
@ -99,7 +103,6 @@ interface IState {
};
syncErrorData: any;
useCompactLayout: boolean;
serverNoticeEvents: MatrixEvent[];
}
/**
@ -144,8 +147,6 @@ class LoggedInView extends React.PureComponent<IProps, IState> {
syncErrorData: undefined,
// use compact timeline view
useCompactLayout: SettingsStore.getValue('useCompactLayout'),
// any currently active server notice events
serverNoticeEvents: [],
};
// stash the MatrixClient in case we log out before we are unmounted
@ -293,6 +294,8 @@ class LoggedInView extends React.PureComponent<IProps, IState> {
if (oldSyncState === 'PREPARED' && syncState === 'SYNCING') {
this._updateServerNoticeEvents();
} else {
this._calculateServerLimitToast(data);
}
};
@ -303,11 +306,24 @@ class LoggedInView extends React.PureComponent<IProps, IState> {
}
};
_calculateServerLimitToast(syncErrorData, usageLimitEventContent?) {
const error = syncErrorData && syncErrorData.error && syncErrorData.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED";
if (error) {
usageLimitEventContent = syncErrorData.error.data;
}
if (usageLimitEventContent) {
showServerLimitToast(usageLimitEventContent.limit_type, usageLimitEventContent.admin_contact, error);
} else {
hideServerLimitToast();
}
}
_updateServerNoticeEvents = async () => {
const roomLists = RoomListStoreTempProxy.getRoomLists();
if (!roomLists[DefaultTagID.ServerNotice]) return [];
const pinnedEvents = [];
const events = [];
for (const room of roomLists[DefaultTagID.ServerNotice]) {
const pinStateEvent = room.currentState.getStateEvents("m.room.pinned_events", "");
@ -317,12 +333,18 @@ class LoggedInView extends React.PureComponent<IProps, IState> {
for (const eventId of pinnedEventIds) {
const timeline = await this._matrixClient.getEventTimeline(room.getUnfilteredTimelineSet(), eventId, 0);
const event = timeline.getEvents().find(ev => ev.getId() === eventId);
if (event) pinnedEvents.push(event);
if (event) events.push(event);
}
}
this.setState({
serverNoticeEvents: pinnedEvents,
const usageLimitEvent = events.find((e) => {
return (
e && e.getType() === 'm.room.message' &&
e.getContent()['server_notice_type'] === 'm.server_notice.usage_limit_reached'
);
});
this._calculateServerLimitToast(this.state.syncErrorData, usageLimitEvent && usageLimitEvent.getContent());
};
_onPaste = (ev) => {
@ -600,7 +622,6 @@ class LoggedInView extends React.PureComponent<IProps, IState> {
const ToastContainer = sdk.getComponent('structures.ToastContainer');
const NewVersionBar = sdk.getComponent('globals.NewVersionBar');
const UpdateCheckBar = sdk.getComponent('globals.UpdateCheckBar');
const ServerLimitBar = sdk.getComponent('globals.ServerLimitBar');
let pageElement;
@ -644,25 +665,8 @@ class LoggedInView extends React.PureComponent<IProps, IState> {
break;
}
const usageLimitEvent = this.state.serverNoticeEvents.find((e) => {
return (
e && e.getType() === 'm.room.message' &&
e.getContent()['server_notice_type'] === 'm.server_notice.usage_limit_reached'
);
});
let topBar;
if (this.state.syncErrorData && this.state.syncErrorData.error.errcode === 'M_RESOURCE_LIMIT_EXCEEDED') {
topBar = <ServerLimitBar kind='hard'
adminContact={this.state.syncErrorData.error.data.admin_contact}
limitType={this.state.syncErrorData.error.data.limit_type}
/>;
} else if (usageLimitEvent) {
topBar = <ServerLimitBar kind='soft'
adminContact={usageLimitEvent.getContent().admin_contact}
limitType={usageLimitEvent.getContent().limit_type}
/>;
} else if (this.props.hasNewVersion) {
if (this.props.hasNewVersion) {
topBar = <NewVersionBar version={this.props.version} newVersion={this.props.newVersion}
releaseNotes={this.props.newVersionReleaseNotes}
/>;

View File

@ -1,99 +0,0 @@
/*
Copyright 2018 New Vector Ltd
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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import classNames from 'classnames';
import { _td } from '../../../languageHandler';
import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
export default createReactClass({
propTypes: {
// 'hard' if the logged in user has been locked out, 'soft' if they haven't
kind: PropTypes.string,
adminContact: PropTypes.string,
// The type of limit that has been hit.
limitType: PropTypes.string.isRequired,
},
getDefaultProps: function() {
return {
kind: 'hard',
};
},
render: function() {
const toolbarClasses = {
'mx_MatrixToolbar': true,
};
let adminContact;
let limitError;
if (this.props.kind === 'hard') {
toolbarClasses['mx_MatrixToolbar_error'] = true;
adminContact = messageForResourceLimitError(
this.props.limitType,
this.props.adminContact,
{
'': _td("Please <a>contact your service administrator</a> to continue using the service."),
},
);
limitError = messageForResourceLimitError(
this.props.limitType,
this.props.adminContact,
{
'monthly_active_user': _td("This homeserver has hit its Monthly Active User limit."),
'': _td("This homeserver has exceeded one of its resource limits."),
},
);
} else {
toolbarClasses['mx_MatrixToolbar_info'] = true;
adminContact = messageForResourceLimitError(
this.props.limitType,
this.props.adminContact,
{
'': _td("Please <a>contact your service administrator</a> to get this limit increased."),
},
);
limitError = messageForResourceLimitError(
this.props.limitType,
this.props.adminContact,
{
'monthly_active_user': _td(
"This homeserver has hit its Monthly Active User limit so " +
"<b>some users will not be able to log in</b>.",
),
'': _td(
"This homeserver has exceeded one of its resource limits so " +
"<b>some users will not be able to log in</b>.",
),
},
{'b': sub => <b>{sub}</b>},
);
}
return (
<div className={classNames(toolbarClasses)}>
<div className="mx_MatrixToolbar_content">
{limitError}
{' '}
{adminContact}
</div>
</div>
);
},
});

View File

@ -0,0 +1,50 @@
/*
Copyright 2020 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.
*/
import React from "react";
import { _t, _td } from "../languageHandler";
import GenericToast from "../components/views/toasts/GenericToast";
import ToastStore from "../stores/ToastStore";
import {messageForResourceLimitError} from "../utils/ErrorUtils";
const TOAST_KEY = "serverlimit";
export const showToast = (limitType: string, adminContact?: string, syncError?: boolean) => {
const errorText = messageForResourceLimitError(limitType, adminContact, {
'monthly_active_user': _td("Your homeserver has exceeded its user limit."),
'': _td("Your homeserver has exceeded one of its resource limits."),
});
const contactText = messageForResourceLimitError(limitType, adminContact, {
'': _td("Contact your <a>server admin</a>."),
});
ToastStore.sharedInstance().addOrReplaceToast({
key: TOAST_KEY,
title: _t("Notifications"),
props: {
description: <React.Fragment>{errorText} {contactText}</React.Fragment>,
acceptLabel: _t("Ok"),
onAccept: hideToast,
},
component: GenericToast,
priority: 20,
});
};
export const hideToast = () => {
ToastStore.sharedInstance().dismissToast(TOAST_KEY);
};