From 52708afa7c02b54e334a2cdee835c7f9253b2c29 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 21 Oct 2018 17:00:10 -0600 Subject: [PATCH] Add Spotify widget Fixes https://github.com/turt2live/matrix-dimension/issues/133 --- package-lock.json | 5 +++ package.json | 1 + .../20181021164245-AddSpotifyWidget.ts | 23 ++++++++++++++ web/app/app.module.ts | 4 +++ web/app/app.routing.ts | 8 +++++ .../spotify/spotify.widget.component.html | 12 +++++++ .../spotify/spotify.widget.component.scss | 0 .../spotify/spotify.widget.component.ts | 30 ++++++++++++++++++ web/app/home/home.component.html | 4 +++ web/app/shared/models/widget.ts | 1 + .../shared/registry/integrations.registry.ts | 5 ++- .../spotify/spotify.component.ts | 22 +++++++++++++ web/public/img/avatars/spotify.png | Bin 0 -> 5277 bytes 13 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/db/migrations/20181021164245-AddSpotifyWidget.ts create mode 100644 web/app/configs/widget/spotify/spotify.widget.component.html create mode 100644 web/app/configs/widget/spotify/spotify.widget.component.scss create mode 100644 web/app/configs/widget/spotify/spotify.widget.component.ts create mode 100644 web/app/widget-wrappers/spotify/spotify.component.ts create mode 100644 web/public/img/avatars/spotify.png diff --git a/package-lock.json b/package-lock.json index 5058497..cb10c72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10855,6 +10855,11 @@ "extend-shallow": "^3.0.0" } }, + "spotify-uri": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spotify-uri/-/spotify-uri-1.0.0.tgz", + "integrity": "sha1-5pKCizTzH04ajfIT/oeQlMfrpVU=" + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", diff --git a/package.json b/package.json index b11872a..76288eb 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "require-dir-all": "^0.4.15", "sequelize": "^4.39.1", "sequelize-typescript": "^0.6.6", + "spotify-uri": "^1.0.0", "sqlite3": "^4.0.2", "typescript": "^2.9.2", "typescript-rest": "^1.7.0", diff --git a/src/db/migrations/20181021164245-AddSpotifyWidget.ts b/src/db/migrations/20181021164245-AddSpotifyWidget.ts new file mode 100644 index 0000000..1450738 --- /dev/null +++ b/src/db/migrations/20181021164245-AddSpotifyWidget.ts @@ -0,0 +1,23 @@ +import { QueryInterface } from "sequelize"; + +export default { + up: (queryInterface: QueryInterface) => { + return Promise.resolve() + .then(() => queryInterface.bulkInsert("dimension_widgets", [ + { + type: "spotify", + name: "Spotify", + avatarUrl: "/img/avatars/spotify.png", + isEnabled: true, + isPublic: true, + description: "Share music with the room", + } + ])); + }, + down: (queryInterface: QueryInterface) => { + return Promise.resolve() + .then(() => queryInterface.bulkDelete("dimension_widgets", { + type: "spotify", + })); + } +} \ No newline at end of file diff --git a/web/app/app.module.ts b/web/app/app.module.ts index c341a25..c81f14e 100644 --- a/web/app/app.module.ts +++ b/web/app/app.module.ts @@ -99,6 +99,8 @@ import { GenericFullscreenWidgetWrapperComponent } from "./widget-wrappers/gener import { GrafanaWidgetConfigComponent } from "./configs/widget/grafana/grafana.widget.component"; import { TradingViewWidgetConfigComponent } from "./configs/widget/tradingview/tradingview.widget.component"; import { TradingViewWidgetWrapperComponent } from "./widget-wrappers/tradingview/tradingview.component"; +import { SpotifyWidgetConfigComponent } from "./configs/widget/spotify/spotify.widget.component"; +import { SpotifyWidgetWrapperComponent } from "./widget-wrappers/spotify/spotify.component"; @NgModule({ imports: [ @@ -181,6 +183,8 @@ import { TradingViewWidgetWrapperComponent } from "./widget-wrappers/tradingview GrafanaWidgetConfigComponent, TradingViewWidgetConfigComponent, TradingViewWidgetWrapperComponent, + SpotifyWidgetConfigComponent, + SpotifyWidgetWrapperComponent, // Vendor ], diff --git a/web/app/app.routing.ts b/web/app/app.routing.ts index e0c926b..eb5de37 100644 --- a/web/app/app.routing.ts +++ b/web/app/app.routing.ts @@ -37,6 +37,8 @@ import { GenericFullscreenWidgetWrapperComponent } from "./widget-wrappers/gener import { GrafanaWidgetConfigComponent } from "./configs/widget/grafana/grafana.widget.component"; import { TradingViewWidgetConfigComponent } from "./configs/widget/tradingview/tradingview.widget.component"; import { TradingViewWidgetWrapperComponent } from "./widget-wrappers/tradingview/tradingview.component"; +import { SpotifyWidgetConfigComponent } from "./configs/widget/spotify/spotify.widget.component"; +import { SpotifyWidgetWrapperComponent } from "./widget-wrappers/spotify/spotify.component"; const routes: Routes = [ {path: "", component: HomeComponent}, @@ -174,6 +176,11 @@ const routes: Routes = [ component: TradingViewWidgetConfigComponent, data: {breadcrumb: "TradingView Widgets", name: "TradingView Widgets"}, }, + { + path: "spotify", + component: SpotifyWidgetConfigComponent, + data: {breadcrumb: "Spotify Widgets", name: "Spotify Widgets"}, + }, ], }, { @@ -233,6 +240,7 @@ const routes: Routes = [ {path: "stickerpicker", component: StickerPickerWidgetWrapperComponent}, {path: "generic-fullscreen", component: GenericFullscreenWidgetWrapperComponent}, {path: "tradingview", component: TradingViewWidgetWrapperComponent}, + {path: "spotify", component: SpotifyWidgetWrapperComponent}, ] }, ]; diff --git a/web/app/configs/widget/spotify/spotify.widget.component.html b/web/app/configs/widget/spotify/spotify.widget.component.html new file mode 100644 index 0000000..39288f8 --- /dev/null +++ b/web/app/configs/widget/spotify/spotify.widget.component.html @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/web/app/configs/widget/spotify/spotify.widget.component.scss b/web/app/configs/widget/spotify/spotify.widget.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/web/app/configs/widget/spotify/spotify.widget.component.ts b/web/app/configs/widget/spotify/spotify.widget.component.ts new file mode 100644 index 0000000..18774bb --- /dev/null +++ b/web/app/configs/widget/spotify/spotify.widget.component.ts @@ -0,0 +1,30 @@ +import { DISABLE_AUTOMATIC_WRAPPING, WidgetComponent } from "../widget.component"; +import { EditableWidget, WIDGET_SPOTIFY } from "../../../shared/models/widget"; +import { Component } from "@angular/core"; + +@Component({ + templateUrl: "spotify.widget.component.html", + styleUrls: ["spotify.widget.component.scss"], +}) +export class SpotifyWidgetConfigComponent extends WidgetComponent { + + constructor() { + super(WIDGET_SPOTIFY, "Spotify", DISABLE_AUTOMATIC_WRAPPING, "spotify"); + } + + protected OnNewWidgetPrepared(widget: EditableWidget): void { + widget.dimension.newData.uri = ""; + } + + protected OnWidgetBeforeAdd(widget: EditableWidget): void { + this.setSpotifyUrl(widget); + } + + protected OnWidgetBeforeEdit(widget: EditableWidget) { + this.setSpotifyUrl(widget); + } + + private setSpotifyUrl(widget: EditableWidget) { + widget.dimension.newUrl = window.location.origin + "/widgets/spotify?uri=$uri"; + } +} \ No newline at end of file diff --git a/web/app/home/home.component.html b/web/app/home/home.component.html index 9f42ff9..2302620 100644 --- a/web/app/home/home.component.html +++ b/web/app/home/home.component.html @@ -43,6 +43,10 @@ TradingView +
+ + Spotify +
YouTube diff --git a/web/app/shared/models/widget.ts b/web/app/shared/models/widget.ts index 828834f..d59d053 100644 --- a/web/app/shared/models/widget.ts +++ b/web/app/shared/models/widget.ts @@ -10,6 +10,7 @@ export const WIDGET_GRAFANA = ["grafana", "dimension-grafana"]; export const WIDGET_TWITCH = ["twitch", "dimension-twitch"]; export const WIDGET_STICKER_PICKER = ["m.stickerpicker"]; export const WIDGET_TRADINGVIEW = ["tradingview", "dimension-tradingview"]; +export const WIDGET_SPOTIFY = ["spotify", "dimension-spotify"]; export interface EditableWidget { /** diff --git a/web/app/shared/registry/integrations.registry.ts b/web/app/shared/registry/integrations.registry.ts index 27b12ba..96ad818 100644 --- a/web/app/shared/registry/integrations.registry.ts +++ b/web/app/shared/registry/integrations.registry.ts @@ -5,7 +5,7 @@ import { WIDGET_GOOGLE_CALENDAR, WIDGET_GOOGLE_DOCS, WIDGET_GRAFANA, - WIDGET_JITSI, + WIDGET_JITSI, WIDGET_SPOTIFY, WIDGET_TRADINGVIEW, WIDGET_TWITCH, WIDGET_YOUTUBE @@ -56,6 +56,9 @@ export class IntegrationsRegistry { "tradingview": { types: WIDGET_TRADINGVIEW, }, + "spotify": { + types: WIDGET_SPOTIFY, + }, }, }; diff --git a/web/app/widget-wrappers/spotify/spotify.component.ts b/web/app/widget-wrappers/spotify/spotify.component.ts new file mode 100644 index 0000000..4ce693d --- /dev/null +++ b/web/app/widget-wrappers/spotify/spotify.component.ts @@ -0,0 +1,22 @@ +import { Component } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; +import * as spotifyUri from "spotify-uri"; +import { DomSanitizer, SafeUrl } from "@angular/platform-browser"; + +@Component({ + selector: "my-spotify-widget-wrapper", + templateUrl: "../fullpage-iframe/fullpage-iframe.component.html", + styleUrls: ["../fullpage-iframe/fullpage-iframe.component.scss"], +}) +export class SpotifyWidgetWrapperComponent { + + public embedUrl: SafeUrl = null; + + constructor(activatedRoute: ActivatedRoute, sanitizer: DomSanitizer) { + let params: any = activatedRoute.snapshot.queryParams; + const spotifyUrl = spotifyUri.parse(params.uri); + const spotifyEmbedUrl = spotifyUri.formatEmbedURL(spotifyUrl); + this.embedUrl = sanitizer.bypassSecurityTrustResourceUrl(spotifyEmbedUrl); + } + +} diff --git a/web/public/img/avatars/spotify.png b/web/public/img/avatars/spotify.png new file mode 100644 index 0000000000000000000000000000000000000000..9bd55daff5c91e2875731a2bef68d43563a9fd23 GIT binary patch literal 5277 zcmV;O6k_X%P)wX zK~#9!?VWjeQ)Rx#zh}$Vv}u~AD@{uaWtBx10r8^XpnwY?;9PM-9Yr0{D}pd{Q5hZK zs(9yuI`9mm-nd z@_x^|{oddE`w@~PN$6(qk^qnB1qT6MiH9hO;3cv7?*su*AVConR0IWvprIxh&;-@p zsseO(_!1}G7xA+v4`)1u$n#dfDZ1ejS+EiZuf&6w1n>|p2@C=xNT>)3DuRKUWS}F| z&{G=pQ6*uZIt4?u=@_g@?ecX)bfp%|iX7~s3q_n2-#Cur8|MjJ^p?w7WcX<}l4%p3H&4eT{V*6v9Y}&y1a6Nn>yBcx{Q!=-F2E(R zU7{N_kUEUgW#Yc*n=wg0R1vtPvGs`S92S(WgH5dO(vzBG+JrU9^D#t|78YZ5$OZnS z_B(uR+lzB-akpBYT&GFH!^TONWf(u;^{n2o7{-dNC$!NLhqbCJqEa zbbo;hyp?#v`Z;zvve1*5Ww;Sb%(G#p4c%AZt@cA$ShgM_B=l6)CO?fSkt4g8z@=O@ zmX!Yk`|E#!0x&Id6qd)&4N7a4UEpsWC-7*=YDLwnP!kL`S{7r3wolg;c$IZ4R#)#- z)NF&L<~f*en$ood_J|yQTeuP@JQo!OJHTZ9aQv;;g03NOk+%wum#oIGY>}c|Cm5zl z$NF9i0zNJWRNw+{C1w=7hU#vsjF7j4kM!{=}xH90DyqI0M0<6fvpEl^Tz#fsq<0Y$=F;_+kIVs-(Anb&}IZw+g za4A=*qb%%_iKa5gb@ovpX;X|H2mZI0w0|z}lMKIO{3$ zU*HFe-VW<8O0@B>yYo!x+IBzFrtAGDwcmxrZ#jWB!b}?wM;TzG^@t|*Fi<+^NiFoG z1`(tNYJ!HEWI%%kO^{cd?PVnnlGO0iEwNxl4lc=ydeIH1;DKGNN3GyQjo?HzUk591 zN2Orzasuai%W$y%48}(c>b$_L$l+t#UfCaVm?j-#b^S3y+Xut788A_ikRV;r0_AWR zzubV|R9>~#J$Yx7$jxEM{wgfreQe0q5!)lXdL&^)SirlKeL$iPH z_dzfVW5y%K$(Ugng9uUs3S?LwvFr?jB!ZU&R10<3S(k;+>^~seTN2V|vM^?RpYcY= z1^%+`D4r^P&*uVf(_fDzakG)GO6UAMm-b1*SW(&^)t8Em#IXnb>T)P(!7$>%E=vY&=!{tf9a{Tq)A2#d ze_>zx3d}R!8nF9T33i;nDpJA~0&lH5dN zIo>i9daWqts!+;T!^+p8O0dHzc)&w|Ac+tmLX@ubJ0yt)I~WBD6hVR^Xc$NxV(BQv z(FP>YG3dpZU}4NiQze9a-jKwY@KMS_oM(%%sO){5^5pq^ul@C>@t@HXt`*oWx=`q? z^l!%K&c=83r#l=<$S$~0C%9k}ojBpn#VJo7PPy}N!CM;iO75ddM1OS(uG6Gph$an* zj1du}7Ez=Y8d4RMXXvNyg&k=x;nj*wSYP|KPxm-bf2QSS(lK`qW)}Q8Ak+1wakKGQ z%xx|HJEovNL12)^5*t-Nne2qGlp zHJ&jh0pMpprsWDP^Rp)pZ&q!^;0sUTwaQJX7d@R?m)is<^0*401uo{QE(v_bQ>Z8+ zBY&&;8pAF;gXhcEBb)8m-tl9_YkV$Gf`k&T`qCJj7r>AKfuhN6js)58lOPaF84yoL zBbJUr6s1EXslCGbLx2D)@odyA7yfVI~L111I;0(f^Wqb5hC83Wx5ot_3QkYmI zFfoX0cD#%9+l(hlB5DOEs)Pn7y9(ZhQmzJtoE3TA3gmc8Q5&GJ3GMNbZ7+5@vhb*J zGH%fiK{8{4OJs4vor}%(?{OdiCrHY<+J=|j!Mmh8@|XME-}{P%G2_mt8!#<$6b5N5 zVbN>2L>AvUf5z9&<*PJ8jqPd6&{vfdl6c8} z^)f0mEGjdm8^$*7TnX4(cL?uR??iFqBqm&OG$t;g#YQhdInWX+?C!lBX{z`xKNF@1 z5)?t=zUT?KFM0yB5710xjSl1w-C1_(p2$S z5PKIkTbAHt-!*vHI4P{2j}^H~>tMN<9pZci!GICN>OSKmxLz#5?BBL0@%}-}mu|UN}V$T%rda ziEGYDC`bahMgvB}+e&~Ynvza7B%IU`D(FZxB1m;WgM79vG=t&V3>?gO6Wi>Ev94x! z(4FC%CbTpK5~NHGd40{-m}R)JQ&~N&yd7DtY@GC5#2HTk3OOs-rUa7`4_*=>K!7MU zSfnnuN;M>%Z2V6Upg=XAJfuMr6x0NbB-(_5ng-8}>$Mr^E%WJ%>4vemJ#r)tyUyat zl6T>jyg?DT$uLAza5iab-b=Ejk9*E^H+~;`$2Cc!cu7DhSA#OX23f9b{NVZ(M_lKF zZbAeatZ1WknHZ-VfOJ&?;u_7Nfrgg^yjcDLw%L!!HnD9Yg^9(%j5k5l@(yWg-YY2K zt7Wag2aFSOgEkX2f)l$OS@@y;ENTTu$P!Jq27`u4Q!E{YN%~=!W4H+xl{uhgd{y@o zo-BP=*6%S;or2xH{{+G*xTQPtmn$3oZ4gICV{Y`#m>M|}NpuYKl-BQizEJjepQG1x zgz>t8*kD-%QcW-c_ptA7RPr|bZ`C$T&Rd2l`7dKp+53J6?S9cbOV(#LH4ZT}O;FHN z8b!qpAVESQXGNjiicjs|W0W=%i_9}INNwqKtJaem=m@oJ8ybnU@zOfDk19z~&j*gW zvoWV|CGN;yj<>B}bn03WlB~N`iA>BTfy2r2(iO?$D)4{RJCJ&A9yZwypkDN}d(DR0 zee$h=K_HnnT@rYxHeFFEK)hJ~0jB1?f)8u|-Rfsfx-Vjd^;6lNfdtWPMQiqpPCYj- zY%7gI!%hwXqA|_~(QMSX^v*VolTD*#!-`sj1VL&ri3pM;`}*^82B|Gr-)jM4s3?#G z0Z|fh)SZn-i&x9K2d^S%obLM`G$eD$FS?()*EL5ELqRXbgmhIR(wI1;FlNLv(TFA^ z5Y-qbtKqDW8XAIW)9+Z4B(M?(m&n2?df*V(IiOn-A1A3p`mrJZJ)wjV)0{GPpsTi3$4aaHDQu zKR|Y0v5(Bi@;H&7JoF~+hu3QL$&GHXjzO3-iAGnW7t)fg)Be)mgQnX#Nexj!$uf_ z#%NupOoM(LV(7>&zXXb>qw$b&5;j|2#QyY^7%6jdXP*Stw<0hA%rV^5cOS37zF%juTi_^##s` zAS>M4iNC`=hH-5RTq`&+A@@aDHsX`$7(5;`1u3dn9C4k)*N)?;798Lu9$rZZ=?t~W ze`~C+KOQnp!nlY5KHp1_MEs9+3)a=_3EJ~(2o=uvTX(HJ;A(+INyP6;*5F&`N%Um2 zgbFhZ<1jUH1cqqRVW4!Kx}Fs|OwL>8(+PcFcp~O@{2}h%7K}jo?s1_Xf zr)?iHvmeJF%0I-f9Xv1}5hOR=R3^UF9l=)pW!EInSJZ8R4YqxlUho>`6s$xUSJUQa zvs}S3hP;*dNb5_w*8VU=lZNXwX^NsPjjs}iAKm9MCU+rTt=NPL?%ExqZ=EM`+EXC= zvy9gbY;!-q)tn7-E}6O;CMps$qQ+smVGKMXhmUIijXlm|vL4F?8lv%Sv@F7CT|eIh z27nuLUkLlNusxL_n%>x%_EMXlY4^;^hLlB0O@=A!lAmt(GwlkT%EV!o;YOu4!;EK5 zcXen#yiNo`;Gdgumrvx_B25ht}R%$v#ypuG)!(Fpa z0t3JZZ6Ex>JV&YRAhS04X$;Z!?(}s&#cp`QGzF9O!1)NJW(Zk;25{aK>8!N!R0d3vR+DI58$? zVbJ10b?26QIODB=MF|X81hi;MkA3MYk;=p=D)}+y{?z9$0Sy5euom0|D{`1sxI)R~ z;=^otOX^a;Qy0iCup~8{t$(WYJ?wTIQ{HnrA;3h;##1{KOEH3{*QLqix zCO_@75hJ7mH?hxo8jH){M+I+F)Vz#TCJyf;&G*Ut7*+xUKn?G}vWicz%aNrh3t*n{ zH+VjFdZ#xI!dBoWw%HG3dF93~7ZM>*n5if%kH5cD`?+08;HK8Ru4Z>Ya}{?5o;BTt z$6{^^N~;a2z)hU>6ycfDwaE3BHJ|hCZqT4GP-DTm9^d2Gb-b$Mjgf3Af`o-JV`}6`%ruOXJq3>