WIP on AppTile2 transformation
This commit is contained in:
parent
96fa34eecf
commit
4ea3376abf
4 changed files with 106 additions and 52 deletions
|
@ -108,7 +108,6 @@ export default class AppTile extends React.Component {
|
||||||
return !!currentlyAllowedWidgets[newProps.app.eventId];
|
return !!currentlyAllowedWidgets[newProps.app.eventId];
|
||||||
};
|
};
|
||||||
|
|
||||||
const PersistedElement = sdk.getComponent("elements.PersistedElement");
|
|
||||||
return {
|
return {
|
||||||
initialising: true, // True while we are mangling the widget URL
|
initialising: true, // True while we are mangling the widget URL
|
||||||
// True while the iframe content is loading
|
// True while the iframe content is loading
|
||||||
|
@ -190,7 +189,6 @@ export default class AppTile extends React.Component {
|
||||||
// if it's not remaining on screen, get rid of the PersistedElement container
|
// if it's not remaining on screen, get rid of the PersistedElement container
|
||||||
if (!ActiveWidgetStore.getWidgetPersistence(this.props.app.id)) {
|
if (!ActiveWidgetStore.getWidgetPersistence(this.props.app.id)) {
|
||||||
ActiveWidgetStore.destroyPersistentWidget(this.props.app.id);
|
ActiveWidgetStore.destroyPersistentWidget(this.props.app.id);
|
||||||
const PersistedElement = sdk.getComponent("elements.PersistedElement");
|
|
||||||
PersistedElement.destroyElement(this._persistKey);
|
PersistedElement.destroyElement(this._persistKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
77
src/components/views/elements/AppTile2.tsx
Normal file
77
src/components/views/elements/AppTile2.tsx
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 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 { ClientWidgetApi, Widget, WidgetKind } from "matrix-widget-api";
|
||||||
|
import * as React from "react";
|
||||||
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
widget: Widget;
|
||||||
|
kind: WidgetKind;
|
||||||
|
room?: Room;
|
||||||
|
|
||||||
|
// TODO: All the showUIElement props
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AppTile2 extends React.PureComponent<IProps, IState> {
|
||||||
|
private messaging: ClientWidgetApi;
|
||||||
|
private iframeRef = React.createRef<HTMLIFrameElement>();
|
||||||
|
|
||||||
|
public constructor(props: IProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
if (props.kind === WidgetKind.Room && !props.room) {
|
||||||
|
throw new Error("Expected room when supplied with a room widget");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
loading: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private get isMixedContent(): boolean {
|
||||||
|
const myProtocol = window.location.protocol;
|
||||||
|
const widgetProtocol = new URL(this.props.widget.templateUrl).protocol;
|
||||||
|
return myProtocol === 'https:' && widgetProtocol !== 'https:';
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
if (!this.iframeRef.current) {
|
||||||
|
throw new Error("iframe has not yet been associated - fix the render code");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Provide capabilities to widget messaging
|
||||||
|
|
||||||
|
if (this.props.kind === WidgetKind.Room) {
|
||||||
|
this.messaging = WidgetMessagingStore.instance
|
||||||
|
.generateMessagingForRoomWidget(this.props.room, this.props.widget, this.iframeRef.current);
|
||||||
|
} else if (this.props.kind === WidgetKind.Account) {
|
||||||
|
this.messaging = WidgetMessagingStore.instance
|
||||||
|
.generateMessagingForAccountWidget(this.props.widget, this.iframeRef.current);
|
||||||
|
} else {
|
||||||
|
throw new Error("Unexpected widget kind: " + this.props.kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.messaging.once("ready", () => {
|
||||||
|
this.setState({loading: false});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
|
|
||||||
import {MatrixClientPeg} from '../MatrixClientPeg';
|
import {MatrixClientPeg} from '../MatrixClientPeg';
|
||||||
|
import {WidgetMessagingStore} from "./widgets/WidgetMessagingStore";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores information about the widgets active in the app right now:
|
* Stores information about the widgets active in the app right now:
|
||||||
|
@ -29,15 +30,6 @@ class ActiveWidgetStore extends EventEmitter {
|
||||||
super();
|
super();
|
||||||
this._persistentWidgetId = null;
|
this._persistentWidgetId = null;
|
||||||
|
|
||||||
// A list of negotiated capabilities for each widget, by ID
|
|
||||||
// {
|
|
||||||
// widgetId: [caps...],
|
|
||||||
// }
|
|
||||||
this._capsByWidgetId = {};
|
|
||||||
|
|
||||||
// A WidgetMessaging instance for each widget ID
|
|
||||||
this._widgetMessagingByWidgetId = {};
|
|
||||||
|
|
||||||
// What room ID each widget is associated with (if it's a room widget)
|
// What room ID each widget is associated with (if it's a room widget)
|
||||||
this._roomIdByWidgetId = {};
|
this._roomIdByWidgetId = {};
|
||||||
|
|
||||||
|
@ -54,8 +46,6 @@ class ActiveWidgetStore extends EventEmitter {
|
||||||
if (MatrixClientPeg.get()) {
|
if (MatrixClientPeg.get()) {
|
||||||
MatrixClientPeg.get().removeListener('RoomState.events', this.onRoomStateEvents);
|
MatrixClientPeg.get().removeListener('RoomState.events', this.onRoomStateEvents);
|
||||||
}
|
}
|
||||||
this._capsByWidgetId = {};
|
|
||||||
this._widgetMessagingByWidgetId = {};
|
|
||||||
this._roomIdByWidgetId = {};
|
this._roomIdByWidgetId = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +66,16 @@ class ActiveWidgetStore extends EventEmitter {
|
||||||
if (id !== this._persistentWidgetId) return;
|
if (id !== this._persistentWidgetId) return;
|
||||||
const toDeleteId = this._persistentWidgetId;
|
const toDeleteId = this._persistentWidgetId;
|
||||||
|
|
||||||
|
const result = WidgetMessagingStore.instance.findWidgetById(id);
|
||||||
|
if (result) {
|
||||||
|
if (result.room) {
|
||||||
|
WidgetMessagingStore.instance.stopMessagingForRoomWidget(result.room, result.widget);
|
||||||
|
} else {
|
||||||
|
WidgetMessagingStore.instance.stopMessagingForAccountWidget(result.widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.setWidgetPersistence(toDeleteId, false);
|
this.setWidgetPersistence(toDeleteId, false);
|
||||||
this.delWidgetMessaging(toDeleteId);
|
|
||||||
this.delWidgetCapabilities(toDeleteId);
|
|
||||||
this.delRoomId(toDeleteId);
|
this.delRoomId(toDeleteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,43 +96,6 @@ class ActiveWidgetStore extends EventEmitter {
|
||||||
return this._persistentWidgetId;
|
return this._persistentWidgetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
setWidgetCapabilities(widgetId, caps) {
|
|
||||||
this._capsByWidgetId[widgetId] = caps;
|
|
||||||
this.emit('update');
|
|
||||||
}
|
|
||||||
|
|
||||||
widgetHasCapability(widgetId, cap) {
|
|
||||||
return this._capsByWidgetId[widgetId] && this._capsByWidgetId[widgetId].includes(cap);
|
|
||||||
}
|
|
||||||
|
|
||||||
delWidgetCapabilities(widgetId) {
|
|
||||||
delete this._capsByWidgetId[widgetId];
|
|
||||||
this.emit('update');
|
|
||||||
}
|
|
||||||
|
|
||||||
setWidgetMessaging(widgetId, wm) {
|
|
||||||
// Stop any existing widget messaging first
|
|
||||||
this.delWidgetMessaging(widgetId);
|
|
||||||
this._widgetMessagingByWidgetId[widgetId] = wm;
|
|
||||||
this.emit('update');
|
|
||||||
}
|
|
||||||
|
|
||||||
getWidgetMessaging(widgetId) {
|
|
||||||
return this._widgetMessagingByWidgetId[widgetId];
|
|
||||||
}
|
|
||||||
|
|
||||||
delWidgetMessaging(widgetId) {
|
|
||||||
if (this._widgetMessagingByWidgetId[widgetId]) {
|
|
||||||
try {
|
|
||||||
this._widgetMessagingByWidgetId[widgetId].stop();
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to stop listening for widgetMessaging events', e.message);
|
|
||||||
}
|
|
||||||
delete this._widgetMessagingByWidgetId[widgetId];
|
|
||||||
this.emit('update');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getRoomId(widgetId) {
|
getRoomId(widgetId) {
|
||||||
return this._roomIdByWidgetId[widgetId];
|
return this._roomIdByWidgetId[widgetId];
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,25 @@ export class WidgetMessagingStore extends AsyncStoreWithClient<unknown> {
|
||||||
this.widgetMap.clear();
|
this.widgetMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a widget by ID. Not guaranteed to return an accurate result.
|
||||||
|
* @param {string} id The widget ID.
|
||||||
|
* @returns {{widget, room}} The widget and possible room ID, or a falsey value
|
||||||
|
* if not found.
|
||||||
|
* @deprecated Do not use.
|
||||||
|
*/
|
||||||
|
public findWidgetById(id: string): { widget: Widget, room?: Room } {
|
||||||
|
for (const key of this.widgetMap.keys()) {
|
||||||
|
for (const [entityId, surrogate] of this.widgetMap.get(key).entries()) {
|
||||||
|
if (surrogate.definition.id === id) {
|
||||||
|
const room: Room = this.matrixClient?.getRoom(entityId); // will be null for non-rooms
|
||||||
|
return {room, widget: surrogate.definition};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the messaging instance for the widget. Returns a falsey value if none
|
* Gets the messaging instance for the widget. Returns a falsey value if none
|
||||||
* is present.
|
* is present.
|
||||||
|
|
Loading…
Reference in a new issue