Merge remote-tracking branch 'origin/develop' into develop
						commit
						b2fce4809f
					
				|  | @ -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) { | ||||
|  |  | |||
|  | @ -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() { | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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'); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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. | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Weblate
						Weblate