From 1322b12cf6f7a05d927e71dfe0b9435dd74edd82 Mon Sep 17 00:00:00 2001 From: MTRNord Date: Fri, 10 Nov 2017 17:31:46 +0000 Subject: [PATCH] Add Twitch Widget --- config/integrations/twitch_widget.yaml | 7 ++ web/app/app.module.ts | 3 + .../twitch/twitch-config.component.html | 65 +++++++++++++++++ .../twitch/twitch-config.component.scss | 4 ++ .../widget/twitch/twitch-config.component.ts | 70 +++++++++++++++++++ web/app/riot/riot.component.ts | 5 +- web/app/shared/integration.service.ts | 3 + web/app/shared/models/widget.ts | 3 + 8 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 config/integrations/twitch_widget.yaml create mode 100644 web/app/configs/widget/twitch/twitch-config.component.html create mode 100644 web/app/configs/widget/twitch/twitch-config.component.scss create mode 100644 web/app/configs/widget/twitch/twitch-config.component.ts diff --git a/config/integrations/twitch_widget.yaml b/config/integrations/twitch_widget.yaml new file mode 100644 index 0000000..3a870e6 --- /dev/null +++ b/config/integrations/twitch_widget.yaml @@ -0,0 +1,7 @@ +# All this configuration does is make "Youtube Widget" available in the UI +type: "widget" +integrationType: "twitch" +enabled: true +name: "Twitch Livestream" +about: "Embed a Twitch Livestream" +avatar: "img/avatars/twitch.png" diff --git a/web/app/app.module.ts b/web/app/app.module.ts index 74a6208..b62fe1e 100644 --- a/web/app/app.module.ts +++ b/web/app/app.module.ts @@ -28,6 +28,7 @@ import { GenericWidgetWrapperComponent } from "./widget_wrappers/generic/generic import { ToggleFullscreenDirective } from "./shared/toggle-fullscreen.directive"; import { FullscreenButtonComponent } from "./fullscreen-button/fullscreen-button.component"; import { YoutubeWidgetConfigComponent } from "./configs/widget/youtube/youtube-config.component"; +import { TwitchWidgetConfigComponent } from "./configs/widget/twitch/twitch-config.component"; import { VideoWidgetWrapperComponent } from "./widget_wrappers/video/video.component"; @NgModule({ @@ -58,6 +59,7 @@ import { VideoWidgetWrapperComponent } from "./widget_wrappers/video/video.compo ToggleFullscreenDirective, FullscreenButtonComponent, YoutubeWidgetConfigComponent, + TwitchWidgetConfigComponent, VideoWidgetWrapperComponent, // Vendor @@ -78,6 +80,7 @@ import { VideoWidgetWrapperComponent } from "./widget_wrappers/video/video.compo IrcConfigComponent, CustomWidgetConfigComponent, YoutubeWidgetConfigComponent, + TwitchWidgetConfigComponent ] }) export class AppModule { diff --git a/web/app/configs/widget/twitch/twitch-config.component.html b/web/app/configs/widget/twitch/twitch-config.component.html new file mode 100644 index 0000000..1a99d2d --- /dev/null +++ b/web/app/configs/widget/twitch/twitch-config.component.html @@ -0,0 +1,65 @@ +
+ +
+ +

Configure Twitch Livestream widgets

+
+
+
+
+

Loading widgets...

+
+
+
+
+
+
+
+
+ + + + +
+
+
+ {{ widget.name || widget.url }} (added by {{ widget.ownerId }}) + + +
+ + + + +
+
+
+
+
+
diff --git a/web/app/configs/widget/twitch/twitch-config.component.scss b/web/app/configs/widget/twitch/twitch-config.component.scss new file mode 100644 index 0000000..92dce18 --- /dev/null +++ b/web/app/configs/widget/twitch/twitch-config.component.scss @@ -0,0 +1,4 @@ +// component styles are encapsulated and only applied to their components +.widget-item { + margin-top: 3px; +} diff --git a/web/app/configs/widget/twitch/twitch-config.component.ts b/web/app/configs/widget/twitch/twitch-config.component.ts new file mode 100644 index 0000000..066babc --- /dev/null +++ b/web/app/configs/widget/twitch/twitch-config.component.ts @@ -0,0 +1,70 @@ +import { Component } from "@angular/core"; +import { ModalComponent, DialogRef } from "ngx-modialog"; +import { WidgetComponent } from "../widget.component"; +import { ScalarService } from "../../../shared/scalar.service"; +import { ConfigModalContext } from "../../../integration/integration.component"; +import { ToasterService } from "angular2-toaster"; +import { Widget, WIDGET_DIM_TWITCH, WIDGET_SCALAR_TWITCH } from "../../../shared/models/widget"; + +@Component({ + selector: "my-twitchwidget-config", + templateUrl: "twitch-config.component.html", + styleUrls: ["twitch-config.component.scss", "./../../config.component.scss"], +}) +export class TwitchWidgetConfigComponent extends WidgetComponent implements ModalComponent { + + constructor(public dialog: DialogRef, + toaster: ToasterService, + scalarService: ScalarService, + window: Window) { + super( + toaster, + scalarService, + dialog.context.roomId, + window, + WIDGET_DIM_TWITCH, + WIDGET_SCALAR_TWITCH, + dialog.context.integrationId, + "Twitch Widget", + "video", // wrapper + "twitch" // scalar wrapper + ); + } + + public validateAndAddWidget() { + // Replace channel name with path to embedable Twitch Player + const url = "https://player.twitch.tv/?channel="+this.newWidgetUrl; + + // TODO Somehow Validate if it is a valid Username + if (!url) { + this.toaster.pop("warning", "Please enter a Twitch Livestream Channel Name"); + return; + } + + const originalUrl = this.newWidgetUrl; + this.newWidgetUrl = url; + this.addWidget({dimChannelName: originalUrl}); + } + + public validateAndSaveWidget(widget: Widget) { + const url = "https://player.twitch.tv/?channel="+widget.data.dimChannelName; + + // TODO Somehow Validate if it is a valid Username + if (!url) { + this.toaster.pop("warning", "Please enter a Twitch Livestream Channel Name"); + return; + } + + if (!widget.data) widget.data = {}; + + widget.newUrl = url; + widget.data.dimChannelName = widget.data.newDimChannelName; + this.saveWidget(widget); + } + + editWidget(widget: Widget) { + widget.data.newDimChannelName = widget.data.dimChannelName; + super.editWidget(widget); + } + +} diff --git a/web/app/riot/riot.component.ts b/web/app/riot/riot.component.ts index d41dec6..83fd31f 100644 --- a/web/app/riot/riot.component.ts +++ b/web/app/riot/riot.component.ts @@ -6,7 +6,7 @@ import { ToasterService } from "angular2-toaster"; import { Integration } from "../shared/models/integration"; import { IntegrationService } from "../shared/integration.service"; import * as _ from "lodash"; -import { WIDGET_DIM_CUSTOM, WIDGET_DIM_YOUTUBE } from "../shared/models/widget"; +import { WIDGET_DIM_CUSTOM, WIDGET_DIM_YOUTUBE, WIDGET_DIM_TWITCH } from "../shared/models/widget"; import { IntegrationComponent } from "../integration/integration.component"; @Component({ @@ -76,6 +76,9 @@ export class RiotComponent { } else if (this.requestedScreen === "type_" + WIDGET_DIM_YOUTUBE) { type = "widget"; integrationType = "youtube"; + } else if (this.requestedScreen === "type_" + WIDGET_DIM_TWITCH) { + type = "widget"; + integrationType = "twitch"; } else { console.log("Unknown screen requested: " + this.requestedScreen); } diff --git a/web/app/shared/integration.service.ts b/web/app/shared/integration.service.ts index a6e65a6..46f2229 100644 --- a/web/app/shared/integration.service.ts +++ b/web/app/shared/integration.service.ts @@ -6,6 +6,7 @@ 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"; import { YoutubeWidgetConfigComponent } from "../configs/widget/youtube/youtube-config.component"; +import { TwitchWidgetConfigComponent } from "../configs/widget/twitch/twitch-config.component"; @Injectable() export class IntegrationService { @@ -22,6 +23,7 @@ export class IntegrationService { "widget": { "customwidget": true, "youtube": true, + "twitch": true, }, }; @@ -36,6 +38,7 @@ export class IntegrationService { "widget": { "customwidget": CustomWidgetConfigComponent, "youtube": YoutubeWidgetConfigComponent, + "twitch": TwitchWidgetConfigComponent, }, }; diff --git a/web/app/shared/models/widget.ts b/web/app/shared/models/widget.ts index e1017f4..7ef4719 100644 --- a/web/app/shared/models/widget.ts +++ b/web/app/shared/models/widget.ts @@ -7,10 +7,13 @@ export const WIDGET_SCALAR_GOOGLEDOCS = "googledocs"; export const WIDGET_SCALAR_JITSI = "jitsi"; export const WIDGET_SCALAR_YOUTUBE = "youtube"; export const WIDGET_SCALAR_GRAFANA = "grafana"; +//Placeholder until Scalar supports twitch +export const WIDGET_SCALAR_TWITCH = ""; // Dimension has its own set of types to ensure that we don't conflict with Scalar export const WIDGET_DIM_CUSTOM = "dimension-customwidget"; export const WIDGET_DIM_YOUTUBE = "dimension-youtube"; +export const WIDGET_DIM_TWITCH = "dimension-twitch"; export interface Widget { id: string;