diff --git a/ext/src/shim/cast/index.ts b/ext/src/shim/cast/index.ts index 25b3cb7..3f533f5 100755 --- a/ext/src/shim/cast/index.ts +++ b/ext/src/shim/cast/index.ts @@ -33,7 +33,7 @@ import { onMessage, sendMessageResponse } from "../messageBridge"; type ReceiverActionListener = ( receiver: Receiver - , receiverAction: typeof ReceiverAction) => void; + , receiverAction: string) => void; type RequestSessionSuccessCallback = ( session: Session diff --git a/ext/src/shim/framework/GoogleCastLauncher.ts b/ext/src/shim/framework/GoogleCastLauncher.ts new file mode 100644 index 0000000..23a845d --- /dev/null +++ b/ext/src/shim/framework/GoogleCastLauncher.ts @@ -0,0 +1,78 @@ +"use strict"; + +/** + * Custom element for a cast button used by sites that injects + * a cast icon and manages visibility state and event handling. + */ +export default class GoogleCastLauncher extends HTMLElement { + constructor () { + super(); + + this.style.display = "none"; + + const style = document.createElement("style"); + style.textContent = ` + .cast_caf_state_c { + fill: var(--connected-color, #4285f4); + } + .cast_caf_state_d { + fill: var(--disconnected-color, #7d7d7d); + } + .cast_caf_state_h { + opacity: 0; + } + `; + + // tslint:disable:max-line-length + + const SVG_NAMESPACE = "http://www.w3.org/2000/svg"; + + const icon = document.createElementNS(SVG_NAMESPACE, "svg"); + const iconArch0 = document.createElementNS(SVG_NAMESPACE, "path"); + const iconArch1 = document.createElementNS(SVG_NAMESPACE, "path"); + const iconArch2 = document.createElementNS(SVG_NAMESPACE, "path"); + const iconBox = document.createElementNS(SVG_NAMESPACE, "path"); + const iconBoxFill = document.createElementNS(SVG_NAMESPACE, "path"); + + // Set SVG attributes + icon.setAttribute("x", "0"); + icon.setAttribute("y", "0"); + icon.setAttribute("width", "100%"); + icon.setAttribute("height", "100%"); + icon.setAttribute("viewBox", "0 0 24 24"); + + iconArch0.classList.add("cast_caf_state_d"); + iconArch0.setAttribute("id", "cast_caf_icon_arch0"); + iconArch0.setAttribute("d", "M1 18v3h3c0-1.7-1.34-3-3-3z"); + + iconArch1.classList.add("cast_caf_state_d"); + iconArch1.setAttribute("id", "cast_caf_icon_arch1"); + iconArch1.setAttribute("d", "M1 14v2c2.76 0 5 2.2 5 5h2c0-3.87-3.13-7-7-7z"); + + iconArch2.classList.add("cast_caf_state_d"); + iconArch2.setAttribute("id", "cast_caf_icon_arch2"); + iconArch2.setAttribute("d", "M1 10v2c4.97 0 9 4 9 9h2c0-6.08-4.93-11-11-11z"); + + iconBox.classList.add("cast_caf_state_d"); + iconBox.setAttribute("id", "cast_caf_icon_box"); + iconBox.setAttribute("d", "M21 3H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"); + + iconBoxFill.classList.add("cast_caf_state_h"); + iconBoxFill.setAttribute("id", "cast_caf_icon_boxfill"); + iconBoxFill.setAttribute("d", "M5 7v1.63C8 8.6 13.37 14 13.37 17H19V7z"); + + // Add icon paths to SVG + icon.append(iconArch0, iconArch1, iconArch2, iconBox, iconBoxFill); + + // tslint:enable:max-line-length + + + const shadow = this.attachShadow({ mode: "open" }); + shadow.append(icon, style); + + + this.addEventListener("click", ev => { + console.info(" onClick"); + }); + } +} diff --git a/ext/src/shim/framework/classes/CastContext.ts b/ext/src/shim/framework/classes/CastContext.ts index 814f40d..674a28a 100644 --- a/ext/src/shim/framework/classes/CastContext.ts +++ b/ext/src/shim/framework/classes/CastContext.ts @@ -1,20 +1,14 @@ "use strict"; +import * as cast from "../../cast"; + import CastOptions from "./CastOptions"; import CastSession from "./CastSession"; import CastStateEventData from "./CastStateEventData"; import SessionStateEventData from "./SessionStateEventData"; -type EventHandler = (eventData: - CastStateEventData - | SessionStateEventData) => void; - -export default class CastContext { - public addEventListener (type: string, handler: EventHandler): void { - console.info("STUB :: CastContext#addEventListener"); - } - +export default class CastContext extends EventTarget { public endCurrentSession (stopCasting: boolean): void { console.info("STUB :: CastContext#endCurrentSession"); } @@ -34,10 +28,6 @@ export default class CastContext { console.info("STUB :: CastContext#getSessionState"); } - public removeEventListener (type: string, handler: EventHandler): void { - console.info("STUB :: CastContext#removeEventListener"); - } - // @ts-ignore public requestSession (): Promise { console.info("STUB :: CastContext#requestSession"); @@ -47,3 +37,5 @@ export default class CastContext { console.info("STUB :: CastContext#setOptions"); } } + +export const instance = new CastContext(); diff --git a/ext/src/shim/framework/classes/CastSession.ts b/ext/src/shim/framework/classes/CastSession.ts index 7b6ec0b..2ff35ad 100644 --- a/ext/src/shim/framework/classes/CastSession.ts +++ b/ext/src/shim/framework/classes/CastSession.ts @@ -10,28 +10,15 @@ import MediaSessionEventData from "./MediaSessionEventData"; import VolumeEventData from "./VolumeEventData"; -type EventHandler = (eventData: - ApplicationStatusEventData - | ApplicationMetadataEventData - | ActiveInputStateEventData - | MediaSessionEventData - | VolumeEventData) => void; - type MessageListener = (namespace: string, message: string) => void; -export default class CastSession { +export default class CastSession extends EventTarget { constructor (sessionObj: cast.Session, state: string) { + super(); console.info("STUB :: CastSession#constructor"); } - public addEventListener ( - type: string - , handler: EventHandler): void { - - console.info("STUB :: CastSession#addEventListener"); - } - public addMessageListener ( namespace: string , listener: MessageListener): void { @@ -98,13 +85,6 @@ export default class CastSession { console.info("STUB :: CastSession#loadMedia"); } - public removeEventListener ( - type: string - , handler: EventHandler): void { - - console.info("STUB :: CastSession#removeEventListener"); - } - public removeMessageListener ( namespace: string , listener: MessageListener): void { diff --git a/ext/src/shim/framework/classes/RemotePlayerController.ts b/ext/src/shim/framework/classes/RemotePlayerController.ts index ee8311a..b8314de 100644 --- a/ext/src/shim/framework/classes/RemotePlayerController.ts +++ b/ext/src/shim/framework/classes/RemotePlayerController.ts @@ -4,17 +4,12 @@ import RemotePlayer from "./RemotePlayer"; import RemotePlayerChangedEvent from "./RemotePlayerChangedEvent"; -type EventHandler = (event: RemotePlayerChangedEvent) => void; - -export default class RemotePlayerController { +export default class RemotePlayerController extends EventTarget { constructor (player: RemotePlayer) { + super(); console.info("STUB :: RemotePlayerController#constructor"); } - public addEventListener (type: string, handler: EventHandler): void { - console.info("STUB :: RemotePlayerContoller#addEventListener"); - } - public getFormattedTime (timeInSec: number): string { const hours = Math.floor(timeInSec / 3600) % 24; const minutes = Math.floor(timeInSec / 60) % 60; @@ -41,10 +36,6 @@ export default class RemotePlayerController { console.info("STUB :: RemotePlayerController#playOrPause"); } - public removeEventListener (type: string, handler: EventHandler): void { - console.info("STUB :: RemotePlayerController#removeEventListener"); - } - public seek (): void { console.info("STUB :: RemotePlayerController#seek"); } diff --git a/ext/src/shim/framework/index.ts b/ext/src/shim/framework/index.ts index 442ee9d..faaf38c 100644 --- a/ext/src/shim/framework/index.ts +++ b/ext/src/shim/framework/index.ts @@ -6,7 +6,7 @@ import ActiveInputStateEventData from "./classes/ActiveInputStateEventData"; import ApplicationMetadata from "./classes/ApplicationMetadata"; import ApplicationMetadataEventData from "./classes/ApplicationMetadataEventData"; import ApplicationStatusEventData from "./classes/ApplicationStatusEventData"; -import CastContext from "./classes/CastContext"; +import CastContext, { instance } from "./classes/CastContext"; import CastOptions from "./classes/CastOptions"; import CastSession from "./classes/CastSession"; import CastStateEventData from "./classes/CastStateEventData"; @@ -26,12 +26,11 @@ import { ActiveInputState , SessionEventType , SessionState } from "./enums"; +import GoogleCastLauncher from "./GoogleCastLauncher"; import { onMessage } from "../messageBridge"; -let castContext: CastContext = null; - export default { // Enums ActiveInputState, CastContextEventType, CastState, LoggerLevel @@ -52,12 +51,7 @@ export default { ...CastContext , getInstance () { - if (castContext) { - return castContext; - } - - castContext = new CastContext(); - return castContext; + return instance; } } @@ -67,3 +61,19 @@ export default { console.info("STUB :: cast.framework.setLoggerLevel"); } }; + + +/** + * The Framework API defines a element + * and a