Support multiple integration managers behind a labs flag
Fixes https://github.com/vector-im/riot-web/issues/10622 Implements [MSC1957](https://github.com/matrix-org/matrix-doc/pull/1957) Design is not final.
This commit is contained in:
parent
602c338a26
commit
b3cda4b19a
13 changed files with 318 additions and 21 deletions
|
@ -71,6 +71,7 @@
|
||||||
@import "./views/dialogs/_SettingsDialog.scss";
|
@import "./views/dialogs/_SettingsDialog.scss";
|
||||||
@import "./views/dialogs/_ShareDialog.scss";
|
@import "./views/dialogs/_ShareDialog.scss";
|
||||||
@import "./views/dialogs/_SlashCommandHelpDialog.scss";
|
@import "./views/dialogs/_SlashCommandHelpDialog.scss";
|
||||||
|
@import "./views/dialogs/_TabbedIntegrationManagerDialog.scss";
|
||||||
@import "./views/dialogs/_TermsDialog.scss";
|
@import "./views/dialogs/_TermsDialog.scss";
|
||||||
@import "./views/dialogs/_UnknownDeviceDialog.scss";
|
@import "./views/dialogs/_UnknownDeviceDialog.scss";
|
||||||
@import "./views/dialogs/_UploadConfirmDialog.scss";
|
@import "./views/dialogs/_UploadConfirmDialog.scss";
|
||||||
|
|
67
res/css/views/dialogs/_TabbedIntegrationManagerDialog.scss
Normal file
67
res/css/views/dialogs/_TabbedIntegrationManagerDialog.scss
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
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_TabbedIntegrationManagerDialog .mx_Dialog {
|
||||||
|
width: 60%;
|
||||||
|
height: 70%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
max-width: initial;
|
||||||
|
max-height: initial;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_TabbedIntegrationManagerDialog_container {
|
||||||
|
// Full size of the dialog, whatever it is
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
.mx_TabbedIntegrationManagerDialog_currentManager {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-top: 1px solid $accent-color;
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
background-color: #fff;
|
||||||
|
border: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_TabbedIntegrationManagerDialog_tab {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid $accent-color;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
//background-color: $accent-color-50pct;
|
||||||
|
padding: 10px 8px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_TabbedIntegrationManagerDialog_tab:first-child {
|
||||||
|
//margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_TabbedIntegrationManagerDialog_currentTab {
|
||||||
|
background-color: $accent-color;
|
||||||
|
color: $accent-fg-color;
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import ActiveWidgetStore from './stores/ActiveWidgetStore';
|
||||||
import MatrixClientPeg from "./MatrixClientPeg";
|
import MatrixClientPeg from "./MatrixClientPeg";
|
||||||
import RoomViewStore from "./stores/RoomViewStore";
|
import RoomViewStore from "./stores/RoomViewStore";
|
||||||
import {IntegrationManagers} from "./integrations/IntegrationManagers";
|
import {IntegrationManagers} from "./integrations/IntegrationManagers";
|
||||||
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
|
|
||||||
const WIDGET_API_VERSION = '0.0.2'; // Current API version
|
const WIDGET_API_VERSION = '0.0.2'; // Current API version
|
||||||
const SUPPORTED_WIDGET_API_VERSIONS = [
|
const SUPPORTED_WIDGET_API_VERSIONS = [
|
||||||
|
@ -194,11 +195,19 @@ export default class FromWidgetPostMessageApi {
|
||||||
const integId = (data && data.integId) ? data.integId : null;
|
const integId = (data && data.integId) ? data.integId : null;
|
||||||
|
|
||||||
// TODO: Open the right integration manager for the widget
|
// TODO: Open the right integration manager for the widget
|
||||||
IntegrationManagers.sharedInstance().getPrimaryManager().open(
|
if (SettingsStore.isFeatureEnabled("feature_many_integration_managers")) {
|
||||||
MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()),
|
IntegrationManagers.sharedInstance().openAll(
|
||||||
`type_${integType}`,
|
MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()),
|
||||||
integId,
|
`type_${integType}`,
|
||||||
);
|
integId,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
IntegrationManagers.sharedInstance().getPrimaryManager().open(
|
||||||
|
MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()),
|
||||||
|
`type_${integType}`,
|
||||||
|
integId,
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (action === 'set_always_on_screen') {
|
} else if (action === 'set_always_on_screen') {
|
||||||
// This is a new message: there is no reason to support the deprecated widgetData here
|
// This is a new message: there is no reason to support the deprecated widgetData here
|
||||||
const data = event.data.data;
|
const data = event.data.data;
|
||||||
|
|
|
@ -548,8 +548,8 @@ const onMessage = function(event) {
|
||||||
// (See https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage)
|
// (See https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage)
|
||||||
let configUrl;
|
let configUrl;
|
||||||
try {
|
try {
|
||||||
// TODO: Support multiple integration managers
|
if (!openManagerUrl) openManagerUrl = IntegrationManagers.sharedInstance().getPrimaryManager().uiUrl;
|
||||||
configUrl = new URL(IntegrationManagers.sharedInstance().getPrimaryManager().uiUrl);
|
configUrl = new URL(openManagerUrl);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// No integrations UI URL, ignore silently.
|
// No integrations UI URL, ignore silently.
|
||||||
return;
|
return;
|
||||||
|
@ -657,6 +657,7 @@ const onMessage = function(event) {
|
||||||
};
|
};
|
||||||
|
|
||||||
let listenerCount = 0;
|
let listenerCount = 0;
|
||||||
|
let openManagerUrl = null;
|
||||||
module.exports = {
|
module.exports = {
|
||||||
startListening: function() {
|
startListening: function() {
|
||||||
if (listenerCount === 0) {
|
if (listenerCount === 0) {
|
||||||
|
@ -679,4 +680,8 @@ module.exports = {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setOpenManagerUrl: function(url) {
|
||||||
|
openManagerUrl = url;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
172
src/components/views/dialogs/TabbedIntegrationManagerDialog.js
Normal file
172
src/components/views/dialogs/TabbedIntegrationManagerDialog.js
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||||
|
import {Room} from "matrix-js-sdk";
|
||||||
|
import sdk from '../../../index';
|
||||||
|
import {dialogTermsInteractionCallback, TermsNotSignedError} from "../../../Terms";
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import ScalarMessaging from "../../../ScalarMessaging";
|
||||||
|
|
||||||
|
export default class TabbedIntegrationManagerDialog extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
/**
|
||||||
|
* Called with:
|
||||||
|
* * success {bool} True if the user accepted any douments, false if cancelled
|
||||||
|
* * agreedUrls {string[]} List of agreed URLs
|
||||||
|
*/
|
||||||
|
onFinished: PropTypes.func.isRequired,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional room where the integration manager should be open to
|
||||||
|
*/
|
||||||
|
room: PropTypes.instanceOf(Room),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional screen to open on the integration manager
|
||||||
|
*/
|
||||||
|
screen: PropTypes.string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional integration ID to open in the integration manager
|
||||||
|
*/
|
||||||
|
integrationId: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
managers: IntegrationManagers.sharedInstance().getOrderedManagers(),
|
||||||
|
busy: true,
|
||||||
|
currentIndex: 0,
|
||||||
|
currentConnected: false,
|
||||||
|
currentLoading: true,
|
||||||
|
currentScalarClient: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount(): void {
|
||||||
|
this.openManager(0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
openManager = async (i: number, force = false) => {
|
||||||
|
if (i === this.state.currentIndex && !force) return;
|
||||||
|
|
||||||
|
const manager = this.state.managers[i];
|
||||||
|
const client = manager.getScalarClient();
|
||||||
|
this.setState({
|
||||||
|
busy: true,
|
||||||
|
currentIndex: i,
|
||||||
|
currentLoading: true,
|
||||||
|
currentConnected: false,
|
||||||
|
currentScalarClient: client,
|
||||||
|
});
|
||||||
|
|
||||||
|
ScalarMessaging.setOpenManagerUrl(manager.uiUrl);
|
||||||
|
|
||||||
|
client.setTermsInteractionCallback((policyInfo, agreedUrls) => {
|
||||||
|
// To avoid visual glitching of two modals stacking briefly, we customise the
|
||||||
|
// terms dialog sizing when it will appear for the integrations manager so that
|
||||||
|
// it gets the same basic size as the IM's own modal.
|
||||||
|
return dialogTermsInteractionCallback(
|
||||||
|
policyInfo, agreedUrls, 'mx_TermsDialog_forIntegrationsManager',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await client.connect();
|
||||||
|
if (!client.hasCredentials()) {
|
||||||
|
this.setState({
|
||||||
|
busy: false,
|
||||||
|
currentLoading: false,
|
||||||
|
currentConnected: false,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
busy: false,
|
||||||
|
currentLoading: false,
|
||||||
|
currentConnected: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof TermsNotSignedError) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(e);
|
||||||
|
this.setState({
|
||||||
|
busy: false,
|
||||||
|
currentLoading: false,
|
||||||
|
currentConnected: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_renderTabs() {
|
||||||
|
const AccessibleButton = sdk.getComponent("views.elements.AccessibleButton");
|
||||||
|
return this.state.managers.map((m, i) => {
|
||||||
|
const classes = classNames({
|
||||||
|
'mx_TabbedIntegrationManagerDialog_tab': true,
|
||||||
|
'mx_TabbedIntegrationManagerDialog_currentTab': this.state.currentIndex === i,
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<AccessibleButton
|
||||||
|
className={classes}
|
||||||
|
onClick={() => this.openManager(i)}
|
||||||
|
key={`tab_${i}`}
|
||||||
|
disabled={this.state.busy}
|
||||||
|
>
|
||||||
|
{m.name}
|
||||||
|
</AccessibleButton>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderTab() {
|
||||||
|
const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
|
||||||
|
let uiUrl = null;
|
||||||
|
if (this.state.currentScalarClient) {
|
||||||
|
uiUrl = this.state.currentScalarClient.getScalarInterfaceUrlForRoom(
|
||||||
|
this.props.room,
|
||||||
|
this.props.screen,
|
||||||
|
this.props.integrationId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <IntegrationsManager
|
||||||
|
configured={true}
|
||||||
|
loading={this.state.currentLoading}
|
||||||
|
connected={this.state.currentConnected}
|
||||||
|
url={uiUrl}
|
||||||
|
onFinished={() => {/* no-op */}}
|
||||||
|
/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className='mx_TabbedIntegrationManagerDialog_container'>
|
||||||
|
<div className='mx_TabbedIntegrationManagerDialog_tabs'>
|
||||||
|
{this._renderTabs()}
|
||||||
|
</div>
|
||||||
|
<div className='mx_TabbedIntegrationManagerDialog_currentManager'>
|
||||||
|
{this._renderTab()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ import dis from '../../../dispatcher';
|
||||||
import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
|
import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
|
const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
|
||||||
const ENABLE_REACT_PERF = false;
|
const ENABLE_REACT_PERF = false;
|
||||||
|
@ -264,11 +265,19 @@ export default class AppTile extends React.Component {
|
||||||
this.props.onEditClick();
|
this.props.onEditClick();
|
||||||
} else {
|
} else {
|
||||||
// TODO: Open the right manager for the widget
|
// TODO: Open the right manager for the widget
|
||||||
IntegrationManagers.sharedInstance().getPrimaryManager().open(
|
if (SettingsStore.isFeatureEnabled("feature_many_integration_managers")) {
|
||||||
this.props.room,
|
IntegrationManagers.sharedInstance().openAll(
|
||||||
'type_' + this.props.type,
|
this.props.room,
|
||||||
this.props.id,
|
'type_' + this.props.type,
|
||||||
);
|
this.props.id,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
IntegrationManagers.sharedInstance().getPrimaryManager().open(
|
||||||
|
this.props.room,
|
||||||
|
'type_' + this.props.type,
|
||||||
|
this.props.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import PropTypes from 'prop-types';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
export default class ManageIntegsButton extends React.Component {
|
export default class ManageIntegsButton extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -33,7 +34,11 @@ export default class ManageIntegsButton extends React.Component {
|
||||||
if (!managers.hasManager()) {
|
if (!managers.hasManager()) {
|
||||||
managers.openNoManagerDialog();
|
managers.openNoManagerDialog();
|
||||||
} else {
|
} else {
|
||||||
managers.getPrimaryManager().open(this.props.room);
|
if (SettingsStore.isFeatureEnabled("feature_many_integration_managers")) {
|
||||||
|
managers.openAll(this.props.room);
|
||||||
|
} else {
|
||||||
|
managers.getPrimaryManager().open(this.props.room);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ import WidgetUtils from '../../../utils/WidgetUtils';
|
||||||
import WidgetEchoStore from "../../../stores/WidgetEchoStore";
|
import WidgetEchoStore from "../../../stores/WidgetEchoStore";
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
// The maximum number of widgets that can be added in a room
|
// The maximum number of widgets that can be added in a room
|
||||||
const MAX_WIDGETS = 2;
|
const MAX_WIDGETS = 2;
|
||||||
|
@ -128,7 +129,11 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_launchManageIntegrations: function() {
|
_launchManageIntegrations: function() {
|
||||||
IntegrationManagers.sharedInstance().getPrimaryManager().open(this.props.room, 'add_integ');
|
if (SettingsStore.isFeatureEnabled("feature_many_integration_managers")) {
|
||||||
|
IntegrationManagers.sharedInstance().openAll();
|
||||||
|
} else {
|
||||||
|
IntegrationManagers.sharedInstance().getPrimaryManager().open(this.props.room, 'add_integ');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onClickAddWidget: function(e) {
|
onClickAddWidget: function(e) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import WidgetUtils from '../../../utils/WidgetUtils';
|
||||||
import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
|
import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
|
||||||
import PersistedElement from "../elements/PersistedElement";
|
import PersistedElement from "../elements/PersistedElement";
|
||||||
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
const widgetType = 'm.stickerpicker';
|
const widgetType = 'm.stickerpicker';
|
||||||
|
|
||||||
|
@ -349,11 +350,19 @@ export default class Stickerpicker extends React.Component {
|
||||||
*/
|
*/
|
||||||
_launchManageIntegrations() {
|
_launchManageIntegrations() {
|
||||||
// TODO: Open the right integration manager for the widget
|
// TODO: Open the right integration manager for the widget
|
||||||
IntegrationManagers.sharedInstance().getPrimaryManager().open(
|
if (SettingsStore.isFeatureEnabled("feature_many_integration_managers")) {
|
||||||
this.props.room,
|
IntegrationManagers.sharedInstance().openAll(
|
||||||
`type_${widgetType}`,
|
this.props.room,
|
||||||
this.state.widgetId,
|
`type_${widgetType}`,
|
||||||
);
|
this.state.widgetId,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
IntegrationManagers.sharedInstance().getPrimaryManager().open(
|
||||||
|
this.props.room,
|
||||||
|
`type_${widgetType}`,
|
||||||
|
this.state.widgetId,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -43,7 +43,7 @@ export default class IntegrationsManager extends React.Component {
|
||||||
configured: true,
|
configured: true,
|
||||||
connected: true,
|
connected: true,
|
||||||
loading: false,
|
loading: false,
|
||||||
}
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
|
|
|
@ -327,6 +327,7 @@
|
||||||
"Group & filter rooms by custom tags (refresh to apply changes)": "Group & filter rooms by custom tags (refresh to apply changes)",
|
"Group & filter rooms by custom tags (refresh to apply changes)": "Group & filter rooms by custom tags (refresh to apply changes)",
|
||||||
"Render simple counters in room header": "Render simple counters in room header",
|
"Render simple counters in room header": "Render simple counters in room header",
|
||||||
"Use the new, faster, but still experimental composer for writing messages (requires refresh)": "Use the new, faster, but still experimental composer for writing messages (requires refresh)",
|
"Use the new, faster, but still experimental composer for writing messages (requires refresh)": "Use the new, faster, but still experimental composer for writing messages (requires refresh)",
|
||||||
|
"Multiple integration managers": "Multiple integration managers",
|
||||||
"Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing",
|
"Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing",
|
||||||
"Use compact timeline layout": "Use compact timeline layout",
|
"Use compact timeline layout": "Use compact timeline layout",
|
||||||
"Show a placeholder for removed messages": "Show a placeholder for removed messages",
|
"Show a placeholder for removed messages": "Show a placeholder for removed messages",
|
||||||
|
|
|
@ -18,7 +18,7 @@ import SdkConfig from '../SdkConfig';
|
||||||
import sdk from "../index";
|
import sdk from "../index";
|
||||||
import Modal from '../Modal';
|
import Modal from '../Modal';
|
||||||
import {IntegrationManagerInstance, KIND_ACCOUNT, KIND_CONFIG, KIND_HOMESERVER} from "./IntegrationManagerInstance";
|
import {IntegrationManagerInstance, KIND_ACCOUNT, KIND_CONFIG, KIND_HOMESERVER} from "./IntegrationManagerInstance";
|
||||||
import type {MatrixClient, MatrixEvent} from "matrix-js-sdk";
|
import type {MatrixClient, MatrixEvent, Room} from "matrix-js-sdk";
|
||||||
import WidgetUtils from "../utils/WidgetUtils";
|
import WidgetUtils from "../utils/WidgetUtils";
|
||||||
import MatrixClientPeg from "../MatrixClientPeg";
|
import MatrixClientPeg from "../MatrixClientPeg";
|
||||||
import {AutoDiscovery} from "matrix-js-sdk";
|
import {AutoDiscovery} from "matrix-js-sdk";
|
||||||
|
@ -180,6 +180,14 @@ export class IntegrationManagers {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openAll(room: Room = null, screen: string = null, integrationId: string = null): void {
|
||||||
|
const TabbedIntegrationManagerDialog = sdk.getComponent("views.dialogs.TabbedIntegrationManagerDialog");
|
||||||
|
Modal.createTrackedDialog(
|
||||||
|
'Tabbed Integration Manager', '', TabbedIntegrationManagerDialog,
|
||||||
|
{room, screen, integrationId}, 'mx_TabbedIntegrationManagerDialog',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async overwriteManagerOnAccount(manager: IntegrationManagerInstance) {
|
async overwriteManagerOnAccount(manager: IntegrationManagerInstance) {
|
||||||
// TODO: TravisR - We should be logging out of scalar clients.
|
// TODO: TravisR - We should be logging out of scalar clients.
|
||||||
await WidgetUtils.removeIntegrationManagerWidgets();
|
await WidgetUtils.removeIntegrationManagerWidgets();
|
||||||
|
|
|
@ -121,6 +121,12 @@ export const SETTINGS = {
|
||||||
supportedLevels: LEVELS_FEATURE,
|
supportedLevels: LEVELS_FEATURE,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
"feature_many_integration_managers": {
|
||||||
|
isFeature: true,
|
||||||
|
displayName: _td("Multiple integration managers"),
|
||||||
|
supportedLevels: LEVELS_FEATURE,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
"MessageComposerInput.suggestEmoji": {
|
"MessageComposerInput.suggestEmoji": {
|
||||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||||
displayName: _td('Enable Emoji suggestions while typing'),
|
displayName: _td('Enable Emoji suggestions while typing'),
|
||||||
|
|
Loading…
Reference in a new issue