+
diff --git a/web/app/riot/riot.component.ts b/web/app/riot/riot.component.ts
index eca1ca1..e7f6efe 100644
--- a/web/app/riot/riot.component.ts
+++ b/web/app/riot/riot.component.ts
@@ -54,6 +54,12 @@ export class RiotComponent {
private updateIntegrationState(integration: Integration) {
integration.hasConfig = IntegrationService.hasConfig(integration);
+ if (integration.type === "widget") {
+ integration.isEnabled = true;
+ integration.isBroken = false;
+ return Promise.resolve();
+ }
+
if (integration.requirements) {
let keys = _.keys(integration.requirements);
let promises = [];
diff --git a/web/app/shared/integration.service.ts b/web/app/shared/integration.service.ts
index 1a8d462..2705602 100644
--- a/web/app/shared/integration.service.ts
+++ b/web/app/shared/integration.service.ts
@@ -4,6 +4,7 @@ import { RssConfigComponent } from "../configs/rss/rss-config.component";
import { ContainerContent } from "ngx-modialog";
import { IrcConfigComponent } from "../configs/irc/irc-config.component";
import { TravisCiConfigComponent } from "../configs/travisci/travisci-config.component";
+import { CustomWidgetConfigComponent } from "../configs/widget/custom_widget/custom_widget-config.component";
@Injectable()
export class IntegrationService {
@@ -16,7 +17,10 @@ export class IntegrationService {
},
"bridge": {
"irc": true,
- }
+ },
+ "widget": {
+ "customwidget": true
+ },
};
private static components = {
@@ -26,7 +30,10 @@ export class IntegrationService {
},
"bridge": {
"irc": IrcConfigComponent,
- }
+ },
+ "widget": {
+ "customwidget": CustomWidgetConfigComponent,
+ },
};
static isSupported(integration: Integration): boolean {
diff --git a/web/app/shared/models/scalar_responses.ts b/web/app/shared/models/scalar_responses.ts
index 4b3e4be..cc6024a 100644
--- a/web/app/shared/models/scalar_responses.ts
+++ b/web/app/shared/models/scalar_responses.ts
@@ -30,4 +30,19 @@ export interface JoinRuleStateResponse extends ScalarRoomResponse {
response: {
join_rule: string;
};
+}
+
+export interface WidgetsResponse extends ScalarRoomResponse {
+ response: {
+ type: "im.vector.modular.widgets";
+ state_key: string;
+ sender: string;
+ room_id: string;
+ content: {
+ type: string;
+ url: string;
+ name?: string;
+ data?: any;
+ }
+ }[];
}
\ No newline at end of file
diff --git a/web/app/shared/models/widget.ts b/web/app/shared/models/widget.ts
new file mode 100644
index 0000000..9446ef0
--- /dev/null
+++ b/web/app/shared/models/widget.ts
@@ -0,0 +1,42 @@
+import { WidgetsResponse } from "./scalar_responses";
+
+// Scalar's widget types (known)
+export const WIDGET_SCALAR_CUSTOM = "customwidget";
+export const WIDGET_SCALAR_ETHERPAD = "etherpad";
+export const WIDGET_SCALAR_GOOGLEDOCS = "googledocs";
+export const WIDGET_SCALAR_JITSI = "jitsi";
+export const WIDGET_SCALAR_YOUTUBE = "youtube";
+export const WIDGET_SCALAR_GRAFANA = "grafana";
+
+// Dimension has its own set of types to ensure that we don't conflict with Scalar
+export const WIDGET_DIM_CUSTOM = "dimension-customwidget";
+
+export interface Widget {
+ id: string;
+ type: string;
+ url: string;
+ name?: string;
+ data?: any;
+ ownerId?: string;
+
+ // used only in ui
+ newName?: string;
+ newUrl?: string;
+}
+
+export function ScalarToWidgets(scalarResponse: WidgetsResponse): Widget[] {
+ let widgets = [];
+
+ for (let event of scalarResponse.response) {
+ widgets.push({
+ id: event.state_key,
+ type: event.content.type,
+ url: event.content.url,
+ name: event.content.name,
+ data: event.content.data,
+ ownerId: event.sender,
+ });
+ }
+
+ return widgets;
+}
diff --git a/web/app/shared/scalar.service.ts b/web/app/shared/scalar.service.ts
index 7d57ba1..6fc2f71 100644
--- a/web/app/shared/scalar.service.ts
+++ b/web/app/shared/scalar.service.ts
@@ -1,6 +1,12 @@
import { Injectable } from "@angular/core";
import * as randomString from "random-string";
-import { MembershipStateResponse, ScalarSuccessResponse, JoinRuleStateResponse } from "./models/scalar_responses";
+import {
+ MembershipStateResponse,
+ ScalarSuccessResponse,
+ JoinRuleStateResponse,
+ WidgetsResponse
+} from "./models/scalar_responses";
+import { Widget } from "./models/widget";
@Injectable()
export class ScalarService {
@@ -36,6 +42,32 @@ export class ScalarService {
});
}
+ public getWidgets(roomId: string): Promise {
+ return this.callAction("get_widgets", {
+ room_id: roomId
+ });
+ }
+
+ public setWidget(roomId: string, widget: Widget): Promise {
+ return this.callAction("set_widget", {
+ room_id: roomId,
+ widget_id: widget.id,
+ type: widget.type,
+ url: widget.url,
+ name: widget.name,
+ data: widget.data
+ });
+ }
+
+ public deleteWidget(roomId: string, widget: Widget): Promise {
+ return this.callAction("set_widget", {
+ room_id: roomId,
+ widget_id: widget.id,
+ type: widget.type, // required for some reason
+ url: ""
+ });
+ }
+
public close(): void {
this.callAction("close_scalar", {});
}
diff --git a/web/public/img/avatars/customwidget.png b/web/public/img/avatars/customwidget.png
new file mode 100644
index 0000000..8ec4211
Binary files /dev/null and b/web/public/img/avatars/customwidget.png differ