From f44d1426310a4aee7da509c1eceb5f4743380c3b Mon Sep 17 00:00:00 2001 From: hensm Date: Wed, 28 Apr 2021 06:21:50 +0100 Subject: [PATCH] Replace StatusManager --- .eslintrc.json | 2 +- app/src/bridge/components/chromecast/index.ts | 2 +- app/src/bridge/components/discovery.ts | 54 ++---- app/src/bridge/index.ts | 4 +- app/src/bridge/messaging.ts | 14 +- app/src/bridge/types.ts | 10 +- ext/src/background/ShimManager.ts | 14 +- ext/src/background/StatusManager.ts | 163 ----------------- ext/src/background/background.ts | 5 +- ext/src/background/receiverDevices.ts | 167 ++++++++++++++++++ .../NativeReceiverSelector.ts | 4 +- .../receiverSelector/PopupReceiverSelector.ts | 8 +- .../receiverSelector/ReceiverSelector.ts | 10 +- .../ReceiverSelectorManager.ts | 31 ++-- ext/src/lib/bridge.ts | 2 +- ext/src/lib/logger.ts | 8 + ext/src/messaging.ts | 21 ++- ext/src/senders/media/index.ts | 4 +- ext/src/senders/mirroring.ts | 4 +- ext/src/shim/cast/index.ts | 6 +- ext/src/types.ts | 6 +- ext/src/ui/popup/index.tsx | 42 ++--- 22 files changed, 295 insertions(+), 286 deletions(-) delete mode 100644 ext/src/background/StatusManager.ts create mode 100644 ext/src/background/receiverDevices.ts diff --git a/.eslintrc.json b/.eslintrc.json index c3e08d9..ef386cd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -27,7 +27,7 @@ , "comma-style": [ "error", "first" ] , "no-multiple-empty-lines": [ "error", { "max": 2 }] , "no-console": [ "error", { - "allow": [ "info", "error" ] + "allow": [ "info", "warn", "error" ] }] , "operator-linebreak": [ "error", "after", { "overrides": { diff --git a/app/src/bridge/components/chromecast/index.ts b/app/src/bridge/components/chromecast/index.ts index 14c66fa..c7d5ff6 100644 --- a/app/src/bridge/components/chromecast/index.ts +++ b/app/src/bridge/components/chromecast/index.ts @@ -4,7 +4,7 @@ import castv2 from "castv2"; import Session, { NS_CONNECTION, NS_RECEIVER } from "./Session"; import Media from "./Media"; -import { Receiver } from "../../types"; +import { ReceiverDevice } from "../../types"; // Existing counterpart Media/Session objects diff --git a/app/src/bridge/components/discovery.ts b/app/src/bridge/components/discovery.ts index 95786e3..fa41898 100644 --- a/app/src/bridge/components/discovery.ts +++ b/app/src/bridge/components/discovery.ts @@ -2,10 +2,13 @@ import mdns from "mdns"; -import StatusListener from "./chromecast/StatusListener"; -import { ReceiverStatus } from "../types"; import { sendMessage } from "../lib/nativeMessaging"; +import { ReceiverStatus } from "../types"; +import { Message } from "../messaging"; + +import StatusListener from "./chromecast/StatusListener"; + interface CastTxtRecord { id: string; cd: string; rm: string; @@ -34,12 +37,14 @@ function onBrowserServiceUp(service: mdns.Service) { const txtRecord = service.txtRecord as CastTxtRecord; sendMessage({ - subject: "main:serviceUp" + subject: "main:receiverDeviceUp" , data: { - host: service.addresses[0] - , port: service.port - , id: txtRecord.id - , friendlyName: txtRecord.fn + receiverDevice: { + host: service.addresses[0] + , port: service.port + , id: txtRecord.id + , friendlyName: txtRecord.fn + } } }); } @@ -72,41 +77,20 @@ export function startDiscovery(options: InitializeOptions) { return; } - const { id } = service.txtRecord; - const listener = new StatusListener( - service.addresses[0] - , service.port); + service.addresses[0], service.port); listener.on("receiverStatus", (status: ReceiverStatus) => { - const receiverStatusMessage: any = { - subject: "main:updateReceiverStatus" + sendMessage({ + subject: "main:receiverDeviceUpdated" , data: { - id - , status: { - volume: { - level: status.volume.level - , muted: status.volume.muted - } - } + receiverDeviceId: service.txtRecord.id + , status } - }; - - if (status.applications && status.applications.length) { - const application = status.applications[0]; - - receiverStatusMessage.data.status.application = { - appId: application.appId - , displayName: application.displayName - , isIdleScreen: application.isIdleScreen - , statusText: application.statusText - }; - } - - sendMessage(receiverStatusMessage); + }); }); - statusListeners.set(id, listener); + statusListeners.set(service.txtRecord.id, listener); } function onStatusBrowserServiceDown(_service: mdns.Service) { diff --git a/app/src/bridge/index.ts b/app/src/bridge/index.ts index b894783..6667c64 100755 --- a/app/src/bridge/index.ts +++ b/app/src/bridge/index.ts @@ -51,8 +51,8 @@ decodeTransform.on("data", (message: Message) => { } case "bridge:stopReceiverApp": { - const { host, port } = message.data.receiver; - stopReceiverApp(host, port); + const { receiverDevice } = message.data; + stopReceiverApp(receiverDevice.host, receiverDevice.port); break; } diff --git a/app/src/bridge/messaging.ts b/app/src/bridge/messaging.ts index 1e43842..cdd8d08 100644 --- a/app/src/bridge/messaging.ts +++ b/app/src/bridge/messaging.ts @@ -1,6 +1,6 @@ "use strict"; -import { Receiver +import { ReceiverDevice , ReceiverSelectionCast , ReceiverSelectionStop , ReceiverStatus } from "./types"; @@ -127,7 +127,7 @@ type MessageDefinitions = { , "bridge:openReceiverSelector": string , "bridge:closeReceiverSelector": {} - , "bridge:stopReceiverApp": { receiver: Receiver } + , "bridge:stopReceiverApp": { receiverDevice: ReceiverDevice } , "bridge:startMediaServer": { @@ -145,13 +145,21 @@ type MessageDefinitions = { , "mediaCast:mediaServerError": {} - , "main:serviceUp": Receiver + , "main:serviceUp": ReceiverDevice , "main:serviceDown": { id: string } , "main:updateReceiverStatus": { id: string , status: ReceiverStatus } + + + , "main:receiverDeviceUp": { receiverDevice: ReceiverDevice } + , "main:receiverDeviceDown": { receiverDeviceId: string } + , "main:receiverDeviceUpdated": { + receiverDeviceId: string + , status: ReceiverStatus + } } diff --git a/app/src/bridge/types.ts b/app/src/bridge/types.ts index fb9e639..0d1b2f0 100644 --- a/app/src/bridge/types.ts +++ b/app/src/bridge/types.ts @@ -14,8 +14,8 @@ export interface ReceiverStatus { , transportId: string , universalAppId: string }> - , isActiveInput: boolean - , isStandBy: boolean + , isActiveInput?: boolean + , isStandBy?: boolean , userEq: unknown , volume: Volume } @@ -68,17 +68,17 @@ export enum ReceiverSelectionActionType { export interface ReceiverSelectionCast { actionType: ReceiverSelectionActionType.Cast; - receiver: Receiver; + receiver: ReceiverDevice; mediaType: ReceiverSelectorMediaType; filePath?: string; } export interface ReceiverSelectionStop { actionType: ReceiverSelectionActionType.Stop; - receiver: Receiver; + receiver: ReceiverDevice; } -export interface Receiver { +export interface ReceiverDevice { host: string; friendlyName: string; id: string; diff --git a/ext/src/background/ShimManager.ts b/ext/src/background/ShimManager.ts index 64dbb9f..e6b40e2 100644 --- a/ext/src/background/ShimManager.ts +++ b/ext/src/background/ShimManager.ts @@ -12,7 +12,7 @@ import { ReceiverSelectionActionType import ReceiverSelectorManager from "./receiverSelector/ReceiverSelectorManager"; -import StatusManager from "./StatusManager"; +import receiverDevices from "./receiverDevices"; type AnyPort = Port | MessagePort; @@ -37,20 +37,20 @@ export default new class ShimManager { } }); - StatusManager.addEventListener("serviceUp", ev => { + receiverDevices.addEventListener("receiverDeviceUp", ev => { for (const shim of this.activeShims) { shim.contentPort.postMessage({ subject: "shim:serviceUp" - , data: { id: ev.detail.id } + , data: { id: ev.detail.receiverDevice.id } }); } }); - StatusManager.addEventListener("serviceDown", ev => { + receiverDevices.addEventListener("receiverDeviceDown", ev => { for (const shim of this.activeShims) { shim.contentPort.postMessage({ subject: "shim:serviceDown" - , data: { id: ev.detail.id } + , data: { id: ev.detail.receiverDeviceId } }); } }); @@ -170,10 +170,10 @@ export default new class ShimManager { case "main:shimReady": { shim.appId = message.data.appId; - for (const receiver of StatusManager.getReceivers()) { + for (const receiverDevice of receiverDevices.getDevices()) { shim.contentPort.postMessage({ subject: "shim:serviceUp" - , data: { id: receiver.id } + , data: { id: receiverDevice.id } }); } diff --git a/ext/src/background/StatusManager.ts b/ext/src/background/StatusManager.ts deleted file mode 100644 index 0b2d2a1..0000000 --- a/ext/src/background/StatusManager.ts +++ /dev/null @@ -1,163 +0,0 @@ -"use strict"; - -import bridge from "../lib/bridge"; -import logger from "../lib/logger"; -import { Message, Port } from "../messaging"; - -import { TypedEventTarget } from "../lib/TypedEventTarget"; -import { Receiver, ReceiverStatus } from "../types"; - - -interface EventMap { - "serviceUp": Receiver; - "serviceDown": { id: string }; - "statusUpdate": { id: string, status: ReceiverStatus }; -} - -export default new class StatusManager - extends TypedEventTarget { - - private bridgePort: (Port | null) = null; - private receivers = new Map(); - - constructor() { - super(); - - // Bind listeners - this.onBridgePortMessage = this.onBridgePortMessage.bind(this); - this.onBridgePortDisconnect = this.onBridgePortDisconnect.bind(this); - } - - public async init() { - if (!this.bridgePort) { - this.bridgePort = await this.createBridgePort(); - } - } - - public *getReceivers() { - for (const [ , receiver ] of this.receivers) { - if (receiver.status && receiver.status.application - && receiver.status.volume) { - yield receiver; - } - } - } - - public async stopReceiverApp(receiver: Receiver) { - if (!this.bridgePort) { - return; - } - - this.bridgePort.postMessage({ - subject: "bridge:stopReceiverApp" - , data: { receiver } - }); - } - - private async createBridgePort() { - const bridgePort = await bridge.connect(); - bridgePort.onMessage.addListener(this.onBridgePortMessage); - bridgePort.onDisconnect.addListener(this.onBridgePortDisconnect); - - bridgePort.postMessage({ - subject: "bridge:initialize" - , data: { - shouldWatchStatus: true - } - }); - - return bridgePort; - } - - /** - * Handles incoming bridge status messages, manages the - * receiver list, and dispatches events. - */ - private onBridgePortMessage(message: Message) { - switch (message.subject) { - case "main:serviceUp": { - const { data: receiver } = message; - this.receivers.set(receiver.id, receiver); - - this.dispatchEvent(new CustomEvent("serviceUp", { - detail: receiver - })); - - break; - } - - case "main:serviceDown": { - const { data: { id }} = message; - - if (this.receivers.has(id)) { - this.receivers.delete(id); - } - - this.dispatchEvent(new CustomEvent("serviceDown", { - detail: { id } - })); - - break; - } - - case "main:updateReceiverStatus": { - const { data: { id, status }} = message; - const receiver = this.receivers.get(id); - - if (!receiver) { - throw logger.error(`Could not find receiver (${id}) specified in status message.`); - } - - // Merge with existing - this.receivers.set(id, { - ...receiver - , status: { - ...receiver.status - , ...status - } - }); - - this.dispatchEvent(new CustomEvent("statusUpdate", { - detail: { id, status } - })); - } - } - } - - /** - * Runs once the status bridge has disconnected. Sends - * serviceDown messages for all receivers to all shims to - * update receiver availability, then clears the receiver - * list. - * - * Attempts to reinitialize the status bridge after 10 - * seconds. If it fails immediately, this handler will be - * triggered again and the timer is reset for another 10 - * seconds. - */ - private onBridgePortDisconnect() { - for (const [ , receiver ] of this.receivers) { - const serviceDownEvent = new CustomEvent("serviceDown", { - detail: { id: receiver.id } - }); - - this.dispatchEvent(serviceDownEvent); - } - - // Cleanup - this.receivers.clear(); - - if (this.bridgePort) { - this.bridgePort.onDisconnect.removeListener( - this.onBridgePortDisconnect); - this.bridgePort.onMessage.removeListener( - this.onBridgePortMessage); - - this.bridgePort = null; - } - - window.setTimeout(async () => { - this.bridgePort = await this.createBridgePort(); - }, 10000); - } -}; diff --git a/ext/src/background/background.ts b/ext/src/background/background.ts index 1728feb..29f417f 100755 --- a/ext/src/background/background.ts +++ b/ext/src/background/background.ts @@ -11,7 +11,8 @@ import ReceiverSelectorManager from "./receiverSelector/ReceiverSelectorManager"; import ShimManager from "./ShimManager"; -import StatusManager from "./StatusManager"; + +import receiverDevices from "./receiverDevices"; import { initMenus } from "./menus"; import { initWhitelist } from "./whitelist"; @@ -155,7 +156,7 @@ async function init() { await notifyBridgeCompat(); - await StatusManager.init(); + await receiverDevices.init(); await ShimManager.init(); await initMenus(); diff --git a/ext/src/background/receiverDevices.ts b/ext/src/background/receiverDevices.ts new file mode 100644 index 0000000..0f93fde --- /dev/null +++ b/ext/src/background/receiverDevices.ts @@ -0,0 +1,167 @@ +"use strict"; + +import bridge from "../lib/bridge"; +import logger from "../lib/logger"; +import { TypedEventTarget } from "../lib/TypedEventTarget"; + +import messaging, { Message, Port } from "../messaging"; +import { ReceiverDevice, ReceiverStatus } from "../types"; + + +interface EventMap { + "receiverDeviceUp": { receiverDevice: ReceiverDevice } + , "receiverDeviceDown": { receiverDeviceId: string } + , "receiverDeviceUpdated": { + receiverDeviceId: string + , status: ReceiverStatus + } +} + +export default new class extends TypedEventTarget { + /** + * Map of receiver device IDs to devices. Updated as + * receiverDevice messages are received from the bridge. + */ + private receiverDevices = new Map(); + + private bridgePort?: Port; + + + async init() { + if (!this.bridgePort) { + await this.refresh(); + } + } + + /** + * Initialize (or re-initialize) a bridge connection to + * start dispatching events. + */ + async refresh() { + this.bridgePort?.disconnect(); + + const port = await bridge.connect(); + + port.onMessage.addListener(this.onBridgeMessage); + port.onDisconnect.addListener(this.onBridgeDisconnect); + + port.postMessage({ + subject: "bridge:initialize" + , data: { + // Also send back status messages + shouldWatchStatus: true + } + }); + + this.bridgePort = port; + } + + /** + * Get a list of receiver devices + */ + getDevices() { + return Array.from(this.receiverDevices.values()); + } + + /** + * Stops a receiver app running on a given device. + */ + stopReceiverApp(receiverDeviceId: string) { + if (!this.bridgePort) { + logger.error("Failed to stop receiver device, no bridge connection"); + return; + } + + const receiverDevice = this.receiverDevices.get(receiverDeviceId); + if (receiverDevice) { + this.bridgePort.postMessage({ + subject: "bridge:stopReceiverApp" + , data: { receiverDevice } + }); + } + } + + private onBridgeMessage = (message: Message) => { + switch (message.subject) { + case "main:receiverDeviceUp": { + const { receiverDevice } = message.data; + + this.receiverDevices.set(receiverDevice.id, receiverDevice); + this.dispatchEvent( + new CustomEvent("receiverDeviceUp" + , { + detail: { receiverDevice } + })); + + break; + } + + case "main:receiverDeviceDown": { + const { receiverDeviceId } = message.data; + + if (this.receiverDevices.has(receiverDeviceId)) { + this.receiverDevices.delete(receiverDeviceId); + } + this.dispatchEvent( + new CustomEvent("receiverDeviceDown" + , { + detail: { receiverDeviceId } + })); + + break; + } + + case "main:receiverDeviceUpdated": { + const { receiverDeviceId, status } = message.data; + const receiverDevice = + this.receiverDevices.get(receiverDeviceId); + + if (!receiverDevice) { + logger.error(`Receiver ID \`${receiverDeviceId}\` not found!`); + break; + } + + if (receiverDevice.status) { + receiverDevice.status.isActiveInput = status.isActiveInput; + receiverDevice.status.isStandBy = status.isStandBy; + receiverDevice.status.userEq = status.userEq; + receiverDevice.status.volume = status.volume; + + if (status.applications) { + receiverDevice.status.applications = + status.applications; + } + } else { + receiverDevice.status = status; + } + + this.dispatchEvent( + new CustomEvent("receiverDeviceUpdated" + , { + detail: { + receiverDeviceId + , status: receiverDevice.status + } + })); + } + } + } + + private onBridgeDisconnect = () => { + // Notify listeners of device availablility + for (const [ , receiverDevice ] of this.receiverDevices) { + const event = new CustomEvent("receiverDeviceDown", { + detail: { receiverDeviceId: receiverDevice.id } + }); + + this.dispatchEvent(event); + } + + this.receiverDevices.clear(); + + // Re-initialize after 10 seconds + window.setTimeout(() => { + this.refresh(); + }, 10000); + } +}; diff --git a/ext/src/background/receiverSelector/NativeReceiverSelector.ts b/ext/src/background/receiverSelector/NativeReceiverSelector.ts index f8cf3db..7e91364 100644 --- a/ext/src/background/receiverSelector/NativeReceiverSelector.ts +++ b/ext/src/background/receiverSelector/NativeReceiverSelector.ts @@ -8,7 +8,7 @@ import options from "../../lib/options"; import { TypedEventTarget } from "../../lib/TypedEventTarget"; import { getWindowCenteredProps } from "../../lib/utils"; -import { Receiver } from "../../types"; +import { ReceiverDevice } from "../../types"; import ReceiverSelector, { ReceiverSelection @@ -34,7 +34,7 @@ export default class NativeReceiverSelector extends ReceiverSelector { } public async open( - receivers: Receiver[] + receivers: ReceiverDevice[] , defaultMediaType: ReceiverSelectorMediaType , availableMediaTypes: ReceiverSelectorMediaType , appId?: string): Promise { diff --git a/ext/src/background/receiverSelector/PopupReceiverSelector.ts b/ext/src/background/receiverSelector/PopupReceiverSelector.ts index d431f27..47a2bde 100644 --- a/ext/src/background/receiverSelector/PopupReceiverSelector.ts +++ b/ext/src/background/receiverSelector/PopupReceiverSelector.ts @@ -9,7 +9,7 @@ import options from "../../lib/options"; import { TypedEventTarget } from "../../lib/TypedEventTarget"; import { getWindowCenteredProps, WindowCenteredProps } from "../../lib/utils"; -import { Receiver } from "../../types"; +import { ReceiverDevice } from "../../types"; const POPUP_URL = browser.runtime.getURL("ui/popup/index.html"); @@ -20,7 +20,7 @@ export default class PopupReceiverSelector extends ReceiverSelector { private messagePort?: Port; private messagePortDisconnected?: boolean; - private receivers?: Receiver[]; + private receivers?: ReceiverDevice[]; private defaultMediaType?: ReceiverSelectorMediaType; private availableMediaTypes?: ReceiverSelectorMediaType; @@ -53,7 +53,7 @@ export default class PopupReceiverSelector extends ReceiverSelector { } public async open( - receivers: Receiver[] + receivers: ReceiverDevice[] , defaultMediaType: ReceiverSelectorMediaType , availableMediaTypes: ReceiverSelectorMediaType , appId?: string): Promise { @@ -115,7 +115,7 @@ export default class PopupReceiverSelector extends ReceiverSelector { } } - public update(receivers: Receiver[]) { + public update(receivers: ReceiverDevice[]) { this.receivers = receivers; this.messagePort?.postMessage({ subject: "popup:update" diff --git a/ext/src/background/receiverSelector/ReceiverSelector.ts b/ext/src/background/receiverSelector/ReceiverSelector.ts index 53048be..98a5eeb 100644 --- a/ext/src/background/receiverSelector/ReceiverSelector.ts +++ b/ext/src/background/receiverSelector/ReceiverSelector.ts @@ -1,7 +1,7 @@ "use strict"; import { TypedEventTarget } from "../../lib/TypedEventTarget"; -import { Receiver } from "../../types"; +import { ReceiverDevice } from "../../types"; export enum ReceiverSelectorMediaType { @@ -18,13 +18,13 @@ export enum ReceiverSelectionActionType { export interface ReceiverSelectionCast { actionType: ReceiverSelectionActionType.Cast; - receiver: Receiver; + receiver: ReceiverDevice; mediaType: ReceiverSelectorMediaType; filePath?: string; } export interface ReceiverSelectionStop { actionType: ReceiverSelectionActionType.Stop; - receiver: Receiver; + receiver: ReceiverDevice; } export type ReceiverSelection = ReceiverSelectionCast | ReceiverSelectionStop; @@ -43,12 +43,12 @@ export default abstract class ReceiverSelector abstract readonly isOpen: boolean; abstract open ( - receivers: Receiver[] + receivers: ReceiverDevice[] , defaultMediaType: ReceiverSelectorMediaType , availableMediaTypes: ReceiverSelectorMediaType , appId?: string): void; - abstract update (receivers: Receiver[]): void; + abstract update (receivers: ReceiverDevice[]): void; abstract close (): void; } diff --git a/ext/src/background/receiverSelector/ReceiverSelectorManager.ts b/ext/src/background/receiverSelector/ReceiverSelectorManager.ts index 20faa6b..1f7c3f4 100644 --- a/ext/src/background/receiverSelector/ReceiverSelectorManager.ts +++ b/ext/src/background/receiverSelector/ReceiverSelectorManager.ts @@ -4,7 +4,7 @@ import options from "../../lib/options"; import logger from "../../lib/logger"; import ShimManager from "../ShimManager"; -import StatusManager from "../StatusManager"; +import receiverDevices from "../receiverDevices"; import { getMediaTypesForPageUrl } from "../../lib/utils"; @@ -120,12 +120,15 @@ async function getSelection( function onReceiverChange() { - sharedSelector.update(Array.from(StatusManager.getReceivers())); + sharedSelector.update(receiverDevices.getDevices()); } - StatusManager.addEventListener("serviceUp", onReceiverChange); - StatusManager.addEventListener("serviceDown", onReceiverChange); - StatusManager.addEventListener("statusUpdate", onReceiverChange); + receiverDevices.addEventListener( + "receiverDeviceUp", onReceiverChange); + receiverDevices.addEventListener( + "receiverDeviceDown", onReceiverChange); + receiverDevices.addEventListener( + "receiverDeviceUpdated", onReceiverChange); let onSelected: any; @@ -156,9 +159,12 @@ async function getSelection( sharedSelector.removeEventListener("error", onError); sharedSelector.removeEventListener("stop", onStop); - StatusManager.removeEventListener("serviceUp", onReceiverChange); - StatusManager.removeEventListener("serviceDown", onReceiverChange); - StatusManager.removeEventListener("statusUpdate", onReceiverChange); + receiverDevices.removeEventListener( + "receiverDeviceUp", onReceiverChange); + receiverDevices.removeEventListener( + "receiverDeviceDown", onReceiverChange); + receiverDevices.removeEventListener( + "receiverDeviceUpdated", onReceiverChange); } sharedSelector.addEventListener("selected" @@ -191,10 +197,9 @@ async function getSelection( sharedSelector.addEventListener("stop" , storeListener("stop", async ev => { - logger.info("Stopped receiver app", ev.detail); + logger.info("Stopping receiver app...", ev.detail); - await StatusManager.init(); - await StatusManager.stopReceiverApp(ev.detail.receiver); + receiverDevices.stopReceiverApp(ev.detail.receiver.id); resolve({ actionType: ReceiverSelectionActionType.Stop @@ -205,10 +210,10 @@ async function getSelection( // Ensure status manager is initialized - await StatusManager.init(); + await receiverDevices.init(); sharedSelector.open( - Array.from(StatusManager.getReceivers()) + receiverDevices.getDevices() , defaultMediaType , availableMediaTypes , currentShim?.appId); diff --git a/ext/src/lib/bridge.ts b/ext/src/lib/bridge.ts index 5c985cf..0f0a2de 100644 --- a/ext/src/lib/bridge.ts +++ b/ext/src/lib/bridge.ts @@ -9,7 +9,7 @@ import { Message, Port } from "../messaging"; import nativeMessaging from "./nativeMessaging"; import options from "./options"; -import { Receiver } from "../types"; +import { ReceiverDevice } from "../types"; import { ReceiverSelectionCast , ReceiverSelectionStop } from "../background/receiverSelector/ReceiverSelector"; diff --git a/ext/src/lib/logger.ts b/ext/src/lib/logger.ts index af10134..a5408a7 100644 --- a/ext/src/lib/logger.ts +++ b/ext/src/lib/logger.ts @@ -21,6 +21,14 @@ export class Logger { console.info(formattedMessage); } } + public warn(message: string, data?: any) { + const formattedMessage = `${this.prefix} (Warning): ${message}`; + if (data) { + console.warn(formattedMessage, data); + } else { + console.warn(formattedMessage); + } + } public error(message: string, data?: any) { const formattedMessage = `${this.prefix} (Error): ${message}`; if (data) { diff --git a/ext/src/messaging.ts b/ext/src/messaging.ts index d3f88fe..3434de3 100644 --- a/ext/src/messaging.ts +++ b/ext/src/messaging.ts @@ -4,7 +4,7 @@ import Messenger from "./lib/Messenger"; import { TypedPort } from "./lib/TypedPort"; import { BridgeInfo } from "./lib/bridge"; -import { Receiver, ReceiverStatus } from "./types"; +import { ReceiverDevice, ReceiverStatus } from "./types"; import { ReceiverSelectorMediaType } from "./background/receiverSelector"; import { ReceiverSelection, ReceiverSelectionCast, ReceiverSelectionStop } from "./background/receiverSelector/ReceiverSelector"; @@ -34,7 +34,7 @@ import { MediaInfo } from "./shim/cast/media"; type ExtMessageDefinitions = { "popup:init": { appId?: string } , "popup:update": { - receivers: Receiver[] + receivers: ReceiverDevice[] , defaultMediaType?: ReceiverSelectorMediaType , availableMediaTypes?: ReceiverSelectorMediaType } @@ -53,10 +53,10 @@ type ExtMessageDefinitions = { , "main:sessionCreated": {} , "shim:initialized": BridgeInfo - , "shim:serviceUp": { id: Receiver["id"] } - , "shim:serviceDown": { id: Receiver["id"] } + , "shim:serviceUp": { id: ReceiverDevice["id"] } + , "shim:serviceDown": { id: ReceiverDevice["id"] } - , "shim:launchApp": { receiver: Receiver } + , "shim:launchApp": { receiver: ReceiverDevice } } /** @@ -184,7 +184,7 @@ type AppMessageDefinitions = { , "bridge:openReceiverSelector": string , "bridge:closeReceiverSelector": {} - , "bridge:stopReceiverApp": { receiver: Receiver } + , "bridge:stopReceiverApp": { receiverDevice: ReceiverDevice } , "bridge:startMediaServer": { @@ -202,11 +202,10 @@ type AppMessageDefinitions = { , "mediaCast:mediaServerError": {} - , "main:serviceUp": Receiver - , "main:serviceDown": { id: string } - - , "main:updateReceiverStatus": { - id: string + , "main:receiverDeviceUp": { receiverDevice: ReceiverDevice } + , "main:receiverDeviceDown": { receiverDeviceId: string } + , "main:receiverDeviceUpdated": { + receiverDeviceId: string , status: ReceiverStatus } } diff --git a/ext/src/senders/media/index.ts b/ext/src/senders/media/index.ts index d480e20..4fca649 100644 --- a/ext/src/senders/media/index.ts +++ b/ext/src/senders/media/index.ts @@ -5,7 +5,7 @@ import options from "../../lib/options"; import cast, { ensureInit } from "../../shim/export"; import { Message } from "../../messaging"; -import { Receiver } from "../../types"; +import { ReceiverDevice } from "../../types"; function startMediaServer(filePath: string, port: number) @@ -343,7 +343,7 @@ async function registerMediaElementListeners() { interface InitOptions { mediaUrl: string; - receiver: Receiver; + receiver: ReceiverDevice; targetElementId?: number; } diff --git a/ext/src/senders/mirroring.ts b/ext/src/senders/mirroring.ts index 983b7cc..9e21f31 100644 --- a/ext/src/senders/mirroring.ts +++ b/ext/src/senders/mirroring.ts @@ -4,14 +4,14 @@ import options from "../lib/options"; import cast, { ensureInit } from "../shim/export"; import { ReceiverSelectorMediaType } from "../background/receiverSelector"; -import { Receiver } from "../types"; +import { ReceiverDevice } from "../types"; // Variables passed from background const { selectedMedia , selectedReceiver } : { selectedMedia: ReceiverSelectorMediaType - , selectedReceiver: Receiver } = (window as any); + , selectedReceiver: ReceiverDevice } = (window as any); const FX_CAST_RECEIVER_APP_NAMESPACE = "urn:x-cast:fx_cast"; diff --git a/ext/src/shim/cast/index.ts b/ext/src/shim/cast/index.ts index 86ba540..b49e760 100755 --- a/ext/src/shim/cast/index.ts +++ b/ext/src/shim/cast/index.ts @@ -2,7 +2,7 @@ import logger from "../../lib/logger"; -import { Receiver } from "../../types"; +import { ReceiverDevice } from "../../types"; import { onMessage, sendMessageResponse } from "../eventMessageChannel"; import Session from "./Session"; @@ -177,7 +177,7 @@ export function requestSession( } export function _requestSession( - _receiver: Receiver + _receiver: ReceiverDevice , successCallback?: RequestSessionSuccessCallback , errorCallback?: ErrorCallback): void { @@ -414,7 +414,7 @@ onMessage(async message => { } case "shim:launchApp": { - const receiver: Receiver = message.data.receiver; + const receiver: ReceiverDevice = message.data.receiver; _requestSession(receiver , session => { apiConfig.sessionListener(session); diff --git a/ext/src/types.ts b/ext/src/types.ts index c7b1b11..6147995 100644 --- a/ext/src/types.ts +++ b/ext/src/types.ts @@ -3,7 +3,7 @@ import { Volume } from "./shim/cast/dataClasses"; -export interface Receiver { +export interface ReceiverDevice { host: string friendlyName: string , id: string @@ -25,8 +25,8 @@ export interface ReceiverStatus { , transportId: string , universalAppId: string }> - , isActiveInput: boolean - , isStandBy: boolean + , isActiveInput?: boolean + , isStandBy?: boolean , userEq: unknown , volume: Volume } diff --git a/ext/src/ui/popup/index.tsx b/ext/src/ui/popup/index.tsx index d12d45c..95655aa 100755 --- a/ext/src/ui/popup/index.tsx +++ b/ext/src/ui/popup/index.tsx @@ -9,7 +9,7 @@ import options from "../../lib/options"; import messaging, { Message, Port } from "../../messaging"; import { getNextEllipsis } from "../../lib/utils"; -import { Receiver } from "../../types"; +import { ReceiverDevice } from "../../types"; import { ReceiverSelectionActionType , ReceiverSelectorMediaType } from "../../background/receiverSelector"; @@ -31,7 +31,7 @@ browser.runtime.getPlatformInfo() interface PopupAppProps {} interface PopupAppState { - receivers: Receiver[]; + receivers: ReceiverDevice[]; mediaType: ReceiverSelectorMediaType; availableMediaTypes: ReceiverSelectorMediaType; isLoading: boolean; @@ -92,7 +92,7 @@ class PopupApp extends Component { if (availableMediaTypes && defaultMediaType) { this.setState({ - availableMediaTypes: availableMediaTypes + availableMediaTypes , mediaType: defaultMediaType }); } @@ -214,7 +214,7 @@ class PopupApp extends Component { ; } - private onCast(receiver: Receiver) { + private onCast(receiver: ReceiverDevice) { this.setState({ isLoading: true }); @@ -230,7 +230,7 @@ class PopupApp extends Component { }); } - private onStop(receiver: Receiver) { + private onStop(receiver: ReceiverDevice) { this.port?.postMessage({ subject: "receiverSelector:stop" , data: { @@ -274,11 +274,11 @@ class PopupApp extends Component { interface ReceiverEntryProps { - receiver: Receiver; + receiver: ReceiverDevice; isLoading: boolean; canCast: boolean; - onCast (receiver: Receiver): void; - onStop (receiver: Receiver): void; + onCast (receiver: ReceiverDevice): void; + onStop (receiver: ReceiverDevice): void; } interface ReceiverEntryState { @@ -320,28 +320,27 @@ class ReceiverEntry extends Component { } public render() { - if (!this.props.receiver.status) { + const { status } = this.props.receiver; + if (!status) { return; } - const { application } = this.props.receiver.status; + const application = status.applications?.[0]; return (
  • { this.props.receiver.friendlyName }
    -
    - { application.isIdleScreen - ? `${this.props.receiver.host}:${this.props.receiver.port}` - : application.statusText } +
    + { application && !application.isIdleScreen + ? application.statusText + : `${this.props.receiver.host}:${this.props.receiver.port}` }