Merge pull request #2084 from matrix-org/dbkr/store_destroy_persistent_widget

Make ActiveWidgetStore clear persistent widgets
This commit is contained in:
David Baker 2018-07-24 17:12:49 +01:00 committed by GitHub
commit c19a5bd2a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 9 deletions

View file

@ -30,6 +30,7 @@ import DMRoomMap from './utils/DMRoomMap';
import RtsClient from './RtsClient';
import Modal from './Modal';
import sdk from './index';
import ActiveWidgetStore from './stores/ActiveWidgetStore';
/**
* Called at startup, to attempt to build a logged-in Matrix session. It tries
@ -436,6 +437,7 @@ async function startMatrixClient() {
UserActivity.start();
Presence.start();
DMRoomMap.makeShared().start();
ActiveWidgetStore.start();
await MatrixClientPeg.start();
@ -488,6 +490,7 @@ export function stopMatrixClient() {
Notifier.stop();
UserActivity.stop();
Presence.stop();
ActiveWidgetStore.stop();
if (DMRoomMap.shared()) DMRoomMap.shared().stop();
const cli = MatrixClientPeg.get();
if (cli) {

View file

@ -160,12 +160,7 @@ export default class AppTile extends React.Component {
// if it's not remaining on screen, get rid of the PersistedElement container
if (!ActiveWidgetStore.getWidgetPersistence(this.props.id)) {
// FIXME: ActiveWidgetStore should probably worry about this?
const PersistedElement = sdk.getComponent("elements.PersistedElement");
PersistedElement.destroyElement(this._persistKey);
ActiveWidgetStore.delWidgetMessaging(this.props.id);
ActiveWidgetStore.delWidgetCapabilities(this.props.id);
ActiveWidgetStore.delRoomId(this.props.id);
ActiveWidgetStore.destroyPersistentWidget();
}
}
@ -439,6 +434,9 @@ export default class AppTile extends React.Component {
console.warn('Revoking permission to load widget - ', this.state.widgetUrl);
localStorage.removeItem(this.state.widgetPermissionId);
this.setState({hasPermissionToLoad: false});
// Force the widget to be non-persistent
ActiveWidgetStore.destroyPersistentWidget();
}
formatAppTileName() {

View file

@ -27,17 +27,20 @@ module.exports = React.createClass({
getInitialState: function() {
return {
roomId: RoomViewStore.getRoomId(),
persistentWidgetId: ActiveWidgetStore.getPersistentWidgetId(),
};
},
componentWillMount: function() {
this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate);
ActiveWidgetStore.on('update', this._onActiveWidgetStoreUpdate);
},
componentWillUnmount: function() {
if (this._roomStoreToken) {
this._roomStoreToken.remove();
}
ActiveWidgetStore.removeListener('update', this._onActiveWidgetStoreUpdate);
},
_onRoomViewStoreUpdate: function(payload) {
@ -47,9 +50,15 @@ module.exports = React.createClass({
});
},
_onActiveWidgetStoreUpdate: function() {
this.setState({
persistentWidgetId: ActiveWidgetStore.getPersistentWidgetId(),
});
},
render: function() {
if (ActiveWidgetStore.getPersistentWidgetId()) {
const persistentWidgetInRoomId = ActiveWidgetStore.getRoomId(ActiveWidgetStore.getPersistentWidgetId());
if (this.state.persistentWidgetId) {
const persistentWidgetInRoomId = ActiveWidgetStore.getRoomId(this.state.persistentWidgetId);
if (this.state.roomId !== persistentWidgetInRoomId) {
const persistentWidgetInRoom = MatrixClientPeg.get().getRoom(persistentWidgetInRoomId);
// get the widget data

View file

@ -14,14 +14,20 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import EventEmitter from 'events';
import MatrixClientPeg from '../MatrixClientPeg';
import sdk from '../index';
/**
* Stores information about the widgets active in the app right now:
* * What widget is set to remain always-on-screen, if any
* Only one widget may be 'always on screen' at any one time.
* * Negotiated capabilities for active apps
*/
class ActiveWidgetStore {
class ActiveWidgetStore extends EventEmitter {
constructor() {
super();
this._persistentWidgetId = null;
// A list of negotiated capabilities for each widget, by ID
@ -35,6 +41,46 @@ class ActiveWidgetStore {
// What room ID each widget is associated with (if it's a room widget)
this._roomIdByWidgetId = {};
this.onRoomStateEvents = this.onRoomStateEvents.bind(this);
this.dispatcherRef = null;
}
start() {
MatrixClientPeg.get().on('RoomState.events', this.onRoomStateEvents);
}
stop() {
if (MatrixClientPeg.get()) {
MatrixClientPeg.get().removeListener('RoomState.events', this.onRoomStateEvents);
}
this._capsByWidgetId = {};
this._widgetMessagingByWidgetId = {};
this._roomIdByWidgetId = {};
}
onRoomStateEvents(ev, state) {
// XXX: This listens for state events in order to remove the active widget.
// Everything else relies on views listening for events and calling setters
// on this class which is terrible. This store should just listen for events
// and keep itself up to date.
if (ev.getType() !== 'im.vector.modular.widgets') return;
if (ev.getStateKey() === this._persistentWidgetId) {
this.destroyPersistentWidget();
}
}
destroyPersistentWidget() {
const toDeleteId = this._persistentWidgetId;
const PersistedElement = sdk.getComponent("elements.PersistedElement");
PersistedElement.destroyElement('widget_' + toDeleteId);
this.setWidgetPersistence(toDeleteId, false);
this.delWidgetMessaging(toDeleteId);
this.delWidgetCapabilities(toDeleteId);
this.delRoomId(toDeleteId);
}
setWidgetPersistence(widgetId, val) {
@ -43,6 +89,7 @@ class ActiveWidgetStore {
} else if (this._persistentWidgetId !== widgetId && val) {
this._persistentWidgetId = widgetId;
}
this.emit('update');
}
getWidgetPersistence(widgetId) {
@ -55,6 +102,7 @@ class ActiveWidgetStore {
setWidgetCapabilities(widgetId, caps) {
this._capsByWidgetId[widgetId] = caps;
this.emit('update');
}
widgetHasCapability(widgetId, cap) {
@ -63,10 +111,12 @@ class ActiveWidgetStore {
delWidgetCapabilities(widgetId) {
delete this._capsByWidgetId[widgetId];
this.emit('update');
}
setWidgetMessaging(widgetId, wm) {
this._widgetMessagingByWidgetId[widgetId] = wm;
this.emit('update');
}
getWidgetMessaging(widgetId) {
@ -81,6 +131,7 @@ class ActiveWidgetStore {
console.error('Failed to stop listening for widgetMessaging events', e.message);
}
delete this._widgetMessagingByWidgetId[widgetId];
this.emit('update');
}
}
@ -90,10 +141,12 @@ class ActiveWidgetStore {
setRoomId(widgetId, roomId) {
this._roomIdByWidgetId[widgetId] = roomId;
this.emit('update');
}
delRoomId(widgetId) {
delete this._roomIdByWidgetId[widgetId];
this.emit('update');
}
}

View file

@ -1,5 +1,6 @@
/*
Copyright 2017 Vector Creations Ltd
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.