mirror of
https://github.com/element-hq/element-web
synced 2024-11-24 10:15:43 +03:00
Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
12e5eb5f78
10 changed files with 206 additions and 232 deletions
|
@ -61,6 +61,7 @@ import Matrix from 'matrix-js-sdk';
|
||||||
import dis from './dispatcher';
|
import dis from './dispatcher';
|
||||||
import { showUnknownDeviceDialogForCalls } from './cryptodevices';
|
import { showUnknownDeviceDialogForCalls } from './cryptodevices';
|
||||||
import SettingsStore from "./settings/SettingsStore";
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
|
import WidgetUtils from './utils/WidgetUtils';
|
||||||
|
|
||||||
global.mxCalls = {
|
global.mxCalls = {
|
||||||
//room_id: MatrixCall
|
//room_id: MatrixCall
|
||||||
|
@ -412,15 +413,20 @@ function _startCallApp(roomId, type) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const appsStateEvents = room.currentState.getStateEvents('im.vector.modular.widgets');
|
const currentJitsiWidgets = WidgetUtils.getRoomWidgets(room).filter((ev) => {
|
||||||
const currentJitsiWidgets = appsStateEvents.filter((ev) => {
|
return ev.getContent().type === 'jitsi';
|
||||||
ev.getContent().type == 'jitsi';
|
|
||||||
});
|
});
|
||||||
if (currentJitsiWidgets.length > 0) {
|
if (currentJitsiWidgets.length > 0) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"Refusing to start conference call widget in " + roomId +
|
"Refusing to start conference call widget in " + roomId +
|
||||||
" a conference call widget is already present",
|
" a conference call widget is already present",
|
||||||
);
|
);
|
||||||
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
|
||||||
|
Modal.createTrackedDialog('Already have Jitsi Widget', '', ErrorDialog, {
|
||||||
|
title: _t('Call in Progress'),
|
||||||
|
description: _t('A call is already in progress!'),
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,25 +449,20 @@ function _startCallApp(roomId, type) {
|
||||||
queryString
|
queryString
|
||||||
);
|
);
|
||||||
|
|
||||||
const jitsiEvent = {
|
const widgetData = { widgetSessionId };
|
||||||
type: 'jitsi',
|
|
||||||
url: widgetUrl,
|
|
||||||
data: {
|
|
||||||
widgetSessionId: widgetSessionId,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const widgetId = (
|
const widgetId = (
|
||||||
'jitsi_' +
|
'jitsi_' +
|
||||||
MatrixClientPeg.get().credentials.userId +
|
MatrixClientPeg.get().credentials.userId +
|
||||||
'_' +
|
'_' +
|
||||||
Date.now()
|
Date.now()
|
||||||
);
|
);
|
||||||
MatrixClientPeg.get().sendStateEvent(
|
|
||||||
roomId,
|
WidgetUtils.setRoomWidget(roomId, widgetId, 'jitsi', widgetUrl, 'Jitsi', widgetData).then(() => {
|
||||||
'im.vector.modular.widgets',
|
console.log('Jitsi widget added');
|
||||||
jitsiEvent,
|
}).catch((e) => {
|
||||||
widgetId,
|
console.error(e);
|
||||||
).then(() => console.log('Sent jitsi widget state event'), (e) => console.error(e));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Nasty way of making sure we only register
|
// FIXME: Nasty way of making sure we only register
|
||||||
|
|
|
@ -236,8 +236,7 @@ import SdkConfig from './SdkConfig';
|
||||||
import MatrixClientPeg from './MatrixClientPeg';
|
import MatrixClientPeg from './MatrixClientPeg';
|
||||||
import { MatrixEvent } from 'matrix-js-sdk';
|
import { MatrixEvent } from 'matrix-js-sdk';
|
||||||
import dis from './dispatcher';
|
import dis from './dispatcher';
|
||||||
import Widgets from './utils/widgets';
|
import WidgetUtils from './utils/WidgetUtils';
|
||||||
import WidgetUtils from './WidgetUtils';
|
|
||||||
import RoomViewStore from './stores/RoomViewStore';
|
import RoomViewStore from './stores/RoomViewStore';
|
||||||
import { _t } from './languageHandler';
|
import { _t } from './languageHandler';
|
||||||
|
|
||||||
|
@ -297,12 +296,6 @@ function setWidget(event, roomId) {
|
||||||
const widgetData = event.data.data; // optional
|
const widgetData = event.data.data; // optional
|
||||||
const userWidget = event.data.userWidget;
|
const userWidget = event.data.userWidget;
|
||||||
|
|
||||||
const client = MatrixClientPeg.get();
|
|
||||||
if (!client) {
|
|
||||||
sendError(event, _t('You need to be logged in.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// both adding/removing widgets need these checks
|
// both adding/removing widgets need these checks
|
||||||
if (!widgetId || widgetUrl === undefined) {
|
if (!widgetId || widgetUrl === undefined) {
|
||||||
sendError(event, _t("Unable to create widget."), new Error("Missing required widget fields."));
|
sendError(event, _t("Unable to create widget."), new Error("Missing required widget fields."));
|
||||||
|
@ -329,42 +322,8 @@ function setWidget(event, roomId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = {
|
|
||||||
type: widgetType,
|
|
||||||
url: widgetUrl,
|
|
||||||
name: widgetName,
|
|
||||||
data: widgetData,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (userWidget) {
|
if (userWidget) {
|
||||||
const client = MatrixClientPeg.get();
|
WidgetUtils.setUserWidget(widgetId, widgetType, widgetUrl, widgetName, widgetData).then(() => {
|
||||||
const userWidgets = Widgets.getUserWidgets();
|
|
||||||
|
|
||||||
// Delete existing widget with ID
|
|
||||||
try {
|
|
||||||
delete userWidgets[widgetId];
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`$widgetId is non-configurable`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new widget / update
|
|
||||||
if (widgetUrl !== null) {
|
|
||||||
userWidgets[widgetId] = {
|
|
||||||
content: content,
|
|
||||||
sender: client.getUserId(),
|
|
||||||
state_key: widgetId,
|
|
||||||
type: 'm.widget',
|
|
||||||
id: widgetId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// This starts listening for when the echo comes back from the server
|
|
||||||
// since the widget won't appear added until this happens. If we don't
|
|
||||||
// wait for this, the action will complete but if the user is fast enough,
|
|
||||||
// the widget still won't actually be there.
|
|
||||||
client.setAccountData('m.widgets', userWidgets).then(() => {
|
|
||||||
return WidgetUtils.waitForUserWidget(widgetId, widgetUrl !== null);
|
|
||||||
}).then(() => {
|
|
||||||
sendResponse(event, {
|
sendResponse(event, {
|
||||||
success: true,
|
success: true,
|
||||||
});
|
});
|
||||||
|
@ -377,15 +336,7 @@ function setWidget(event, roomId) {
|
||||||
if (!roomId) {
|
if (!roomId) {
|
||||||
sendError(event, _t('Missing roomId.'), null);
|
sendError(event, _t('Missing roomId.'), null);
|
||||||
}
|
}
|
||||||
|
WidgetUtils.setRoomWidget(roomId, widgetId, widgetType, widgetUrl, widgetName, widgetData).then(() => {
|
||||||
if (widgetUrl === null) { // widget is being deleted
|
|
||||||
content = {};
|
|
||||||
}
|
|
||||||
// TODO - Room widgets need to be moved to 'm.widget' state events
|
|
||||||
// https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit?usp=sharing
|
|
||||||
client.sendStateEvent(roomId, "im.vector.modular.widgets", content, widgetId).then(() => {
|
|
||||||
return WidgetUtils.waitForRoomWidget(widgetId, roomId, widgetUrl !== null);
|
|
||||||
}).then(() => {
|
|
||||||
sendResponse(event, {
|
sendResponse(event, {
|
||||||
success: true,
|
success: true,
|
||||||
});
|
});
|
||||||
|
@ -409,21 +360,13 @@ function getWidgets(event, roomId) {
|
||||||
sendError(event, _t('This room is not recognised.'));
|
sendError(event, _t('This room is not recognised.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO - Room widgets need to be moved to 'm.widget' state events
|
// XXX: This gets the raw event object (I think because we can't
|
||||||
// https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit?usp=sharing
|
// send the MatrixEvent over postMessage?)
|
||||||
const stateEvents = room.currentState.getStateEvents("im.vector.modular.widgets");
|
widgetStateEvents = WidgetUtils.getRoomWidgets(room).map((ev) => ev.event);
|
||||||
// Only return widgets which have required fields
|
|
||||||
if (room) {
|
|
||||||
stateEvents.forEach((ev) => {
|
|
||||||
if (ev.getContent().type && ev.getContent().url) {
|
|
||||||
widgetStateEvents.push(ev.event); // return the raw event
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add user widgets (not linked to a specific room)
|
// Add user widgets (not linked to a specific room)
|
||||||
const userWidgets = Widgets.getUserWidgetsArray();
|
const userWidgets = WidgetUtils.getUserWidgetsArray();
|
||||||
widgetStateEvents = widgetStateEvents.concat(userWidgets);
|
widgetStateEvents = widgetStateEvents.concat(userWidgets);
|
||||||
|
|
||||||
sendResponse(event, widgetStateEvents);
|
sendResponse(event, widgetStateEvents);
|
||||||
|
|
|
@ -46,6 +46,7 @@ import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
|
||||||
import RoomViewStore from '../../stores/RoomViewStore';
|
import RoomViewStore from '../../stores/RoomViewStore';
|
||||||
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
||||||
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
||||||
|
import WidgetUtils from '../../utils/WidgetUtils';
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
let debuglog = function() {};
|
let debuglog = function() {};
|
||||||
|
@ -318,14 +319,7 @@ module.exports = React.createClass({
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const appsStateEvents = room.currentState.getStateEvents('im.vector.modular.widgets');
|
return WidgetUtils.getRoomWidgets(room).length > 0;
|
||||||
// any valid widget = show apps
|
|
||||||
for (let i = 0; i < appsStateEvents.length; i++) {
|
|
||||||
if (appsStateEvents[i].getContent().type && appsStateEvents[i].getContent().url) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import WidgetUtils from "../../../WidgetUtils";
|
import WidgetUtils from "../../../utils/WidgetUtils";
|
||||||
|
|
||||||
export default class AppPermission extends React.Component {
|
export default class AppPermission extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ import sdk from '../../../index';
|
||||||
import AppPermission from './AppPermission';
|
import AppPermission from './AppPermission';
|
||||||
import AppWarning from './AppWarning';
|
import AppWarning from './AppWarning';
|
||||||
import MessageSpinner from './MessageSpinner';
|
import MessageSpinner from './MessageSpinner';
|
||||||
import WidgetUtils from '../../../WidgetUtils';
|
import WidgetUtils from '../../../utils/WidgetUtils';
|
||||||
import dis from '../../../dispatcher';
|
import dis from '../../../dispatcher';
|
||||||
|
|
||||||
const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
|
const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:'];
|
||||||
|
@ -319,14 +319,11 @@ export default class AppTile extends React.Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setState({deleting: true});
|
this.setState({deleting: true});
|
||||||
MatrixClientPeg.get().sendStateEvent(
|
|
||||||
|
WidgetUtils.setRoomWidget(
|
||||||
this.props.room.roomId,
|
this.props.room.roomId,
|
||||||
'im.vector.modular.widgets',
|
|
||||||
{}, // empty content
|
|
||||||
this.props.id,
|
this.props.id,
|
||||||
).then(() => {
|
).catch((e) => {
|
||||||
return WidgetUtils.waitForRoomWidget(this.props.id, this.props.room.roomId, false);
|
|
||||||
}).catch((e) => {
|
|
||||||
console.error('Failed to delete widget', e);
|
console.error('Failed to delete widget', e);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.setState({deleting: false});
|
this.setState({deleting: false});
|
||||||
|
|
|
@ -27,7 +27,7 @@ import SdkConfig from '../../../SdkConfig';
|
||||||
import ScalarAuthClient from '../../../ScalarAuthClient';
|
import ScalarAuthClient from '../../../ScalarAuthClient';
|
||||||
import ScalarMessaging from '../../../ScalarMessaging';
|
import ScalarMessaging from '../../../ScalarMessaging';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import WidgetUtils from '../../../WidgetUtils';
|
import WidgetUtils from '../../../utils/WidgetUtils';
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
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
|
||||||
|
@ -163,14 +163,7 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_getApps: function() {
|
_getApps: function() {
|
||||||
const appsStateEvents = this.props.room.currentState.getStateEvents('im.vector.modular.widgets');
|
return WidgetUtils.getRoomWidgets(this.props.room).map((ev) => {
|
||||||
if (!appsStateEvents) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return appsStateEvents.filter((ev) => {
|
|
||||||
return ev.getContent().type && ev.getContent().url;
|
|
||||||
}).map((ev) => {
|
|
||||||
return this._initAppConfig(ev.getStateKey(), ev.getContent(), ev.sender);
|
return this._initAppConfig(ev.getStateKey(), ev.getContent(), ev.sender);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,7 +15,6 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import Widgets from '../../../utils/widgets';
|
|
||||||
import AppTile from '../elements/AppTile';
|
import AppTile from '../elements/AppTile';
|
||||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
|
@ -24,6 +23,7 @@ import SdkConfig from '../../../SdkConfig';
|
||||||
import ScalarAuthClient from '../../../ScalarAuthClient';
|
import ScalarAuthClient from '../../../ScalarAuthClient';
|
||||||
import dis from '../../../dispatcher';
|
import dis from '../../../dispatcher';
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
|
import WidgetUtils from '../../../utils/WidgetUtils';
|
||||||
|
|
||||||
const widgetType = 'm.stickerpicker';
|
const widgetType = 'm.stickerpicker';
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ export default class Stickerpicker extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({showStickers: false});
|
this.setState({showStickers: false});
|
||||||
Widgets.removeStickerpickerWidgets().then(() => {
|
WidgetUtils.removeStickerpickerWidgets().then(() => {
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
console.error('Failed to remove sticker picker widget', e);
|
console.error('Failed to remove sticker picker widget', e);
|
||||||
|
@ -119,7 +119,7 @@ export default class Stickerpicker extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateWidget() {
|
_updateWidget() {
|
||||||
const stickerpickerWidget = Widgets.getStickerpickerWidgets()[0];
|
const stickerpickerWidget = WidgetUtils.getStickerpickerWidgets()[0];
|
||||||
this.setState({
|
this.setState({
|
||||||
stickerpickerWidget,
|
stickerpickerWidget,
|
||||||
widgetId: stickerpickerWidget ? stickerpickerWidget.id : null,
|
widgetId: stickerpickerWidget ? stickerpickerWidget.id : null,
|
||||||
|
|
|
@ -39,13 +39,11 @@
|
||||||
"Conference calling is in development and may not be reliable.": "Conference calling is in development and may not be reliable.",
|
"Conference calling is in development and may not be reliable.": "Conference calling is in development and may not be reliable.",
|
||||||
"Failed to set up conference call": "Failed to set up conference call",
|
"Failed to set up conference call": "Failed to set up conference call",
|
||||||
"Conference call failed.": "Conference call failed.",
|
"Conference call failed.": "Conference call failed.",
|
||||||
|
"Call in Progress": "Call in Progress",
|
||||||
|
"A call is already in progress!": "A call is already in progress!",
|
||||||
"The file '%(fileName)s' failed to upload": "The file '%(fileName)s' failed to upload",
|
"The file '%(fileName)s' failed to upload": "The file '%(fileName)s' failed to upload",
|
||||||
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "The file '%(fileName)s' exceeds this home server's size limit for uploads",
|
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "The file '%(fileName)s' exceeds this home server's size limit for uploads",
|
||||||
"Upload Failed": "Upload Failed",
|
"Upload Failed": "Upload Failed",
|
||||||
"Failure to create room": "Failure to create room",
|
|
||||||
"Server may be unavailable, overloaded, or you hit a bug.": "Server may be unavailable, overloaded, or you hit a bug.",
|
|
||||||
"Send anyway": "Send anyway",
|
|
||||||
"Send": "Send",
|
|
||||||
"Sun": "Sun",
|
"Sun": "Sun",
|
||||||
"Mon": "Mon",
|
"Mon": "Mon",
|
||||||
"Tue": "Tue",
|
"Tue": "Tue",
|
||||||
|
@ -85,7 +83,6 @@
|
||||||
"Failed to invite users to community": "Failed to invite users to community",
|
"Failed to invite users to community": "Failed to invite users to community",
|
||||||
"Failed to invite users to %(groupId)s": "Failed to invite users to %(groupId)s",
|
"Failed to invite users to %(groupId)s": "Failed to invite users to %(groupId)s",
|
||||||
"Failed to add the following rooms to %(groupId)s:": "Failed to add the following rooms to %(groupId)s:",
|
"Failed to add the following rooms to %(groupId)s:": "Failed to add the following rooms to %(groupId)s:",
|
||||||
"Unnamed Room": "Unnamed Room",
|
|
||||||
"Riot does not have permission to send you notifications - please check your browser settings": "Riot does not have permission to send you notifications - please check your browser settings",
|
"Riot does not have permission to send you notifications - please check your browser settings": "Riot does not have permission to send you notifications - please check your browser settings",
|
||||||
"Riot was not given permission to send notifications - please try again": "Riot was not given permission to send notifications - please try again",
|
"Riot was not given permission to send notifications - please try again": "Riot was not given permission to send notifications - please try again",
|
||||||
"Unable to enable Notifications": "Unable to enable Notifications",
|
"Unable to enable Notifications": "Unable to enable Notifications",
|
||||||
|
@ -199,6 +196,11 @@
|
||||||
"%(names)s and %(count)s others are typing|other": "%(names)s and %(count)s others are typing",
|
"%(names)s and %(count)s others are typing|other": "%(names)s and %(count)s others are typing",
|
||||||
"%(names)s and %(count)s others are typing|one": "%(names)s and one other is typing",
|
"%(names)s and %(count)s others are typing|one": "%(names)s and one other is typing",
|
||||||
"%(names)s and %(lastPerson)s are typing": "%(names)s and %(lastPerson)s are typing",
|
"%(names)s and %(lastPerson)s are typing": "%(names)s and %(lastPerson)s are typing",
|
||||||
|
"Failure to create room": "Failure to create room",
|
||||||
|
"Server may be unavailable, overloaded, or you hit a bug.": "Server may be unavailable, overloaded, or you hit a bug.",
|
||||||
|
"Send anyway": "Send anyway",
|
||||||
|
"Send": "Send",
|
||||||
|
"Unnamed Room": "Unnamed Room",
|
||||||
"Your browser does not support the required cryptography extensions": "Your browser does not support the required cryptography extensions",
|
"Your browser does not support the required cryptography extensions": "Your browser does not support the required cryptography extensions",
|
||||||
"Not a valid Riot keyfile": "Not a valid Riot keyfile",
|
"Not a valid Riot keyfile": "Not a valid Riot keyfile",
|
||||||
"Authentication check failed: incorrect password?": "Authentication check failed: incorrect password?",
|
"Authentication check failed: incorrect password?": "Authentication check failed: incorrect password?",
|
||||||
|
@ -311,31 +313,6 @@
|
||||||
"Off": "Off",
|
"Off": "Off",
|
||||||
"On": "On",
|
"On": "On",
|
||||||
"Noisy": "Noisy",
|
"Noisy": "Noisy",
|
||||||
"Invalid alias format": "Invalid alias format",
|
|
||||||
"'%(alias)s' is not a valid format for an alias": "'%(alias)s' is not a valid format for an alias",
|
|
||||||
"Invalid address format": "Invalid address format",
|
|
||||||
"'%(alias)s' is not a valid format for an address": "'%(alias)s' is not a valid format for an address",
|
|
||||||
"not specified": "not specified",
|
|
||||||
"not set": "not set",
|
|
||||||
"Remote addresses for this room:": "Remote addresses for this room:",
|
|
||||||
"Addresses": "Addresses",
|
|
||||||
"The main address for this room is": "The main address for this room is",
|
|
||||||
"Local addresses for this room:": "Local addresses for this room:",
|
|
||||||
"This room has no local addresses": "This room has no local addresses",
|
|
||||||
"New address (e.g. #foo:%(localDomain)s)": "New address (e.g. #foo:%(localDomain)s)",
|
|
||||||
"Invalid community ID": "Invalid community ID",
|
|
||||||
"'%(groupId)s' is not a valid community ID": "'%(groupId)s' is not a valid community ID",
|
|
||||||
"Flair": "Flair",
|
|
||||||
"Showing flair for these communities:": "Showing flair for these communities:",
|
|
||||||
"This room is not showing flair for any communities": "This room is not showing flair for any communities",
|
|
||||||
"New community ID (e.g. +foo:%(localDomain)s)": "New community ID (e.g. +foo:%(localDomain)s)",
|
|
||||||
"You have <a>enabled</a> URL previews by default.": "You have <a>enabled</a> URL previews by default.",
|
|
||||||
"You have <a>disabled</a> URL previews by default.": "You have <a>disabled</a> URL previews by default.",
|
|
||||||
"URL previews are enabled by default for participants in this room.": "URL previews are enabled by default for participants in this room.",
|
|
||||||
"URL previews are disabled by default for participants in this room.": "URL previews are disabled by default for participants in this room.",
|
|
||||||
"In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.": "In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.",
|
|
||||||
"URL Previews": "URL Previews",
|
|
||||||
"When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.",
|
|
||||||
"Cannot add any more widgets": "Cannot add any more widgets",
|
"Cannot add any more widgets": "Cannot add any more widgets",
|
||||||
"The maximum permitted number of widgets have already been added to this room.": "The maximum permitted number of widgets have already been added to this room.",
|
"The maximum permitted number of widgets have already been added to this room.": "The maximum permitted number of widgets have already been added to this room.",
|
||||||
"Add a widget": "Add a widget",
|
"Add a widget": "Add a widget",
|
||||||
|
@ -435,11 +412,11 @@
|
||||||
"numbullet": "numbullet",
|
"numbullet": "numbullet",
|
||||||
"Markdown is disabled": "Markdown is disabled",
|
"Markdown is disabled": "Markdown is disabled",
|
||||||
"Markdown is enabled": "Markdown is enabled",
|
"Markdown is enabled": "Markdown is enabled",
|
||||||
|
"Unpin Message": "Unpin Message",
|
||||||
|
"Jump to message": "Jump to message",
|
||||||
"No pinned messages.": "No pinned messages.",
|
"No pinned messages.": "No pinned messages.",
|
||||||
"Loading...": "Loading...",
|
"Loading...": "Loading...",
|
||||||
"Pinned Messages": "Pinned Messages",
|
"Pinned Messages": "Pinned Messages",
|
||||||
"Unpin Message": "Unpin Message",
|
|
||||||
"Jump to message": "Jump to message",
|
|
||||||
"%(duration)ss": "%(duration)ss",
|
"%(duration)ss": "%(duration)ss",
|
||||||
"%(duration)sm": "%(duration)sm",
|
"%(duration)sm": "%(duration)sm",
|
||||||
"%(duration)sh": "%(duration)sh",
|
"%(duration)sh": "%(duration)sh",
|
||||||
|
@ -572,6 +549,31 @@
|
||||||
"Scroll to unread messages": "Scroll to unread messages",
|
"Scroll to unread messages": "Scroll to unread messages",
|
||||||
"Jump to first unread message.": "Jump to first unread message.",
|
"Jump to first unread message.": "Jump to first unread message.",
|
||||||
"Close": "Close",
|
"Close": "Close",
|
||||||
|
"Invalid alias format": "Invalid alias format",
|
||||||
|
"'%(alias)s' is not a valid format for an alias": "'%(alias)s' is not a valid format for an alias",
|
||||||
|
"Invalid address format": "Invalid address format",
|
||||||
|
"'%(alias)s' is not a valid format for an address": "'%(alias)s' is not a valid format for an address",
|
||||||
|
"not specified": "not specified",
|
||||||
|
"not set": "not set",
|
||||||
|
"Remote addresses for this room:": "Remote addresses for this room:",
|
||||||
|
"Addresses": "Addresses",
|
||||||
|
"The main address for this room is": "The main address for this room is",
|
||||||
|
"Local addresses for this room:": "Local addresses for this room:",
|
||||||
|
"This room has no local addresses": "This room has no local addresses",
|
||||||
|
"New address (e.g. #foo:%(localDomain)s)": "New address (e.g. #foo:%(localDomain)s)",
|
||||||
|
"Invalid community ID": "Invalid community ID",
|
||||||
|
"'%(groupId)s' is not a valid community ID": "'%(groupId)s' is not a valid community ID",
|
||||||
|
"Flair": "Flair",
|
||||||
|
"Showing flair for these communities:": "Showing flair for these communities:",
|
||||||
|
"This room is not showing flair for any communities": "This room is not showing flair for any communities",
|
||||||
|
"New community ID (e.g. +foo:%(localDomain)s)": "New community ID (e.g. +foo:%(localDomain)s)",
|
||||||
|
"You have <a>enabled</a> URL previews by default.": "You have <a>enabled</a> URL previews by default.",
|
||||||
|
"You have <a>disabled</a> URL previews by default.": "You have <a>disabled</a> URL previews by default.",
|
||||||
|
"URL previews are enabled by default for participants in this room.": "URL previews are enabled by default for participants in this room.",
|
||||||
|
"URL previews are disabled by default for participants in this room.": "URL previews are disabled by default for participants in this room.",
|
||||||
|
"In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.": "In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.",
|
||||||
|
"URL Previews": "URL Previews",
|
||||||
|
"When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.",
|
||||||
"Sunday": "Sunday",
|
"Sunday": "Sunday",
|
||||||
"Monday": "Monday",
|
"Monday": "Monday",
|
||||||
"Tuesday": "Tuesday",
|
"Tuesday": "Tuesday",
|
||||||
|
|
|
@ -15,8 +15,9 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import MatrixClientPeg from './MatrixClientPeg';
|
import MatrixClientPeg from '../MatrixClientPeg';
|
||||||
import SdkConfig from "./SdkConfig";
|
import SdkConfig from "../SdkConfig";
|
||||||
|
import dis from '../dispatcher';
|
||||||
import * as url from "url";
|
import * as url from "url";
|
||||||
|
|
||||||
export default class WidgetUtils {
|
export default class WidgetUtils {
|
||||||
|
@ -190,4 +191,137 @@ export default class WidgetUtils {
|
||||||
MatrixClientPeg.get().on('RoomState.events', onRoomStateEvents);
|
MatrixClientPeg.get().on('RoomState.events', onRoomStateEvents);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static setUserWidget(widgetId, widgetType, widgetUrl, widgetName, widgetData) {
|
||||||
|
const content = {
|
||||||
|
type: widgetType,
|
||||||
|
url: widgetUrl,
|
||||||
|
name: widgetName,
|
||||||
|
data: widgetData,
|
||||||
|
};
|
||||||
|
|
||||||
|
const client = MatrixClientPeg.get();
|
||||||
|
const userWidgets = WidgetUtils.getUserWidgets();
|
||||||
|
|
||||||
|
// Delete existing widget with ID
|
||||||
|
try {
|
||||||
|
delete userWidgets[widgetId];
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`$widgetId is non-configurable`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addingWidget = Boolean(widgetUrl);
|
||||||
|
|
||||||
|
// Add new widget / update
|
||||||
|
if (addingWidget) {
|
||||||
|
userWidgets[widgetId] = {
|
||||||
|
content: content,
|
||||||
|
sender: client.getUserId(),
|
||||||
|
state_key: widgetId,
|
||||||
|
type: 'm.widget',
|
||||||
|
id: widgetId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// This starts listening for when the echo comes back from the server
|
||||||
|
// since the widget won't appear added until this happens. If we don't
|
||||||
|
// wait for this, the action will complete but if the user is fast enough,
|
||||||
|
// the widget still won't actually be there.
|
||||||
|
return client.setAccountData('m.widgets', userWidgets).then(() => {
|
||||||
|
return WidgetUtils.waitForUserWidget(widgetId, addingWidget);
|
||||||
|
}).then(() => {
|
||||||
|
dis.dispatch({ action: "user_widget_updated" });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static setRoomWidget(roomId, widgetId, widgetType, widgetUrl, widgetName, widgetData) {
|
||||||
|
let content;
|
||||||
|
|
||||||
|
const addingWidget = Boolean(widgetUrl);
|
||||||
|
|
||||||
|
if (addingWidget) {
|
||||||
|
content = {
|
||||||
|
type: widgetType,
|
||||||
|
url: widgetUrl,
|
||||||
|
name: widgetName,
|
||||||
|
data: widgetData,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
content = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = MatrixClientPeg.get();
|
||||||
|
// TODO - Room widgets need to be moved to 'm.widget' state events
|
||||||
|
// https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit?usp=sharing
|
||||||
|
return client.sendStateEvent(roomId, "im.vector.modular.widgets", content, widgetId).then(() => {
|
||||||
|
return WidgetUtils.waitForRoomWidget(widgetId, roomId, addingWidget);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get room specific widgets
|
||||||
|
* @param {object} room The room to get widgets force
|
||||||
|
* @return {[object]} Array containing current / active room widgets
|
||||||
|
*/
|
||||||
|
static getRoomWidgets(room) {
|
||||||
|
const appsStateEvents = room.currentState.getStateEvents('im.vector.modular.widgets');
|
||||||
|
if (!appsStateEvents) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return appsStateEvents.filter((ev) => {
|
||||||
|
return ev.getContent().type && ev.getContent().url;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get user specific widgets (not linked to a specific room)
|
||||||
|
* @return {object} Event content object containing current / active user widgets
|
||||||
|
*/
|
||||||
|
static getUserWidgets() {
|
||||||
|
const client = MatrixClientPeg.get();
|
||||||
|
if (!client) {
|
||||||
|
throw new Error('User not logged in');
|
||||||
|
}
|
||||||
|
const userWidgets = client.getAccountData('m.widgets');
|
||||||
|
if (userWidgets && userWidgets.getContent()) {
|
||||||
|
return userWidgets.getContent();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get user specific widgets (not linked to a specific room) as an array
|
||||||
|
* @return {[object]} Array containing current / active user widgets
|
||||||
|
*/
|
||||||
|
static getUserWidgetsArray() {
|
||||||
|
return Object.values(WidgetUtils.getUserWidgets());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get active stickerpicker widgets (stickerpickers are user widgets by nature)
|
||||||
|
* @return {[object]} Array containing current / active stickerpicker widgets
|
||||||
|
*/
|
||||||
|
static getStickerpickerWidgets() {
|
||||||
|
const widgets = WidgetUtils.getUserWidgetsArray();
|
||||||
|
return widgets.filter((widget) => widget.content && widget.content.type === "m.stickerpicker");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all stickerpicker widgets (stickerpickers are user widgets by nature)
|
||||||
|
* @return {Promise} Resolves on account data updated
|
||||||
|
*/
|
||||||
|
static removeStickerpickerWidgets() {
|
||||||
|
const client = MatrixClientPeg.get();
|
||||||
|
if (!client) {
|
||||||
|
throw new Error('User not logged in');
|
||||||
|
}
|
||||||
|
const userWidgets = client.getAccountData('m.widgets').getContent() || {};
|
||||||
|
Object.entries(userWidgets).forEach(([key, widget]) => {
|
||||||
|
if (widget.content && widget.content.type === 'm.stickerpicker') {
|
||||||
|
delete userWidgets[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return client.setAccountData('m.widgets', userWidgets);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,90 +0,0 @@
|
||||||
import MatrixClientPeg from '../MatrixClientPeg';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all widgets (user and room) for the current user
|
|
||||||
* @param {object} room The room to get widgets for
|
|
||||||
* @return {[object]} Array containing current / active room and user widget state events
|
|
||||||
*/
|
|
||||||
function getWidgets(room) {
|
|
||||||
const widgets = getRoomWidgets(room);
|
|
||||||
widgets.concat(getUserWidgetsArray());
|
|
||||||
return widgets;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get room specific widgets
|
|
||||||
* @param {object} room The room to get widgets force
|
|
||||||
* @return {[object]} Array containing current / active room widgets
|
|
||||||
*/
|
|
||||||
function getRoomWidgets(room) {
|
|
||||||
const appsStateEvents = room.currentState.getStateEvents('im.vector.modular.widgets');
|
|
||||||
if (!appsStateEvents) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return appsStateEvents.filter((ev) => {
|
|
||||||
return ev.getContent().type && ev.getContent().url;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get user specific widgets (not linked to a specific room)
|
|
||||||
* @return {object} Event content object containing current / active user widgets
|
|
||||||
*/
|
|
||||||
function getUserWidgets() {
|
|
||||||
const client = MatrixClientPeg.get();
|
|
||||||
if (!client) {
|
|
||||||
throw new Error('User not logged in');
|
|
||||||
}
|
|
||||||
const userWidgets = client.getAccountData('m.widgets');
|
|
||||||
let userWidgetContent = {};
|
|
||||||
if (userWidgets && userWidgets.getContent()) {
|
|
||||||
userWidgetContent = userWidgets.getContent();
|
|
||||||
}
|
|
||||||
return userWidgetContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get user specific widgets (not linked to a specific room) as an array
|
|
||||||
* @return {[object]} Array containing current / active user widgets
|
|
||||||
*/
|
|
||||||
function getUserWidgetsArray() {
|
|
||||||
return Object.values(getUserWidgets());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get active stickerpicker widgets (stickerpickers are user widgets by nature)
|
|
||||||
* @return {[object]} Array containing current / active stickerpicker widgets
|
|
||||||
*/
|
|
||||||
function getStickerpickerWidgets() {
|
|
||||||
const widgets = getUserWidgetsArray();
|
|
||||||
return widgets.filter((widget) => widget.content && widget.content.type === "m.stickerpicker");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all stickerpicker widgets (stickerpickers are user widgets by nature)
|
|
||||||
* @return {Promise} Resolves on account data updated
|
|
||||||
*/
|
|
||||||
function removeStickerpickerWidgets() {
|
|
||||||
const client = MatrixClientPeg.get();
|
|
||||||
if (!client) {
|
|
||||||
throw new Error('User not logged in');
|
|
||||||
}
|
|
||||||
const userWidgets = client.getAccountData('m.widgets').getContent() || {};
|
|
||||||
Object.entries(userWidgets).forEach(([key, widget]) => {
|
|
||||||
if (widget.content && widget.content.type === 'm.stickerpicker') {
|
|
||||||
delete userWidgets[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return client.setAccountData('m.widgets', userWidgets);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
|
||||||
getWidgets,
|
|
||||||
getRoomWidgets,
|
|
||||||
getUserWidgets,
|
|
||||||
getUserWidgetsArray,
|
|
||||||
getStickerpickerWidgets,
|
|
||||||
removeStickerpickerWidgets,
|
|
||||||
};
|
|
Loading…
Reference in a new issue