Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2084 from matrix-org/dbkr/store_destroy_persisten…
Browse files Browse the repository at this point in the history
…t_widget

Make ActiveWidgetStore clear persistent widgets
  • Loading branch information
dbkr authored Jul 24, 2018
2 parents fe3850d + cdd73e6 commit c19a5bd
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 9 deletions.
3 changes: 3 additions & 0 deletions src/Lifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -436,6 +437,7 @@ async function startMatrixClient() {
UserActivity.start();
Presence.start();
DMRoomMap.makeShared().start();
ActiveWidgetStore.start();

await MatrixClientPeg.start();

Expand Down Expand Up @@ -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) {
Expand Down
10 changes: 4 additions & 6 deletions src/components/views/elements/AppTile.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down Expand Up @@ -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() {
Expand Down
13 changes: 11 additions & 2 deletions src/components/views/elements/PersistentApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
Expand Down
55 changes: 54 additions & 1 deletion src/stores/ActiveWidgetStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand All @@ -43,6 +89,7 @@ class ActiveWidgetStore {
} else if (this._persistentWidgetId !== widgetId && val) {
this._persistentWidgetId = widgetId;
}
this.emit('update');
}

getWidgetPersistence(widgetId) {
Expand All @@ -55,6 +102,7 @@ class ActiveWidgetStore {

setWidgetCapabilities(widgetId, caps) {
this._capsByWidgetId[widgetId] = caps;
this.emit('update');
}

widgetHasCapability(widgetId, cap) {
Expand All @@ -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) {
Expand All @@ -81,6 +131,7 @@ class ActiveWidgetStore {
console.error('Failed to stop listening for widgetMessaging events', e.message);
}
delete this._widgetMessagingByWidgetId[widgetId];
this.emit('update');
}
}

Expand All @@ -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');
}
}

Expand Down
1 change: 1 addition & 0 deletions src/stores/LifecycleStore.js
Original file line number Diff line number Diff line change
@@ -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.
Expand Down

0 comments on commit c19a5bd

Please sign in to comment.