From 41d8edcab4633179b47328b4cbdeb1f73cf97a1d Mon Sep 17 00:00:00 2001 From: hensm Date: Tue, 31 Aug 2021 08:28:23 +0100 Subject: [PATCH] prettier: Re-format .ts files --- .prettierrc.json | 3 +- app/@types/bplist-creator/index.d.ts | 4 +- app/@types/bplist-parser/index.d.ts | 15 +- app/@types/castv2/index.d.ts | 67 +-- app/@types/fast-srp-hap/index.d.ts | 53 +-- app/src/bridge/components/airplay/auth.ts | 98 ++-- app/src/bridge/components/cast/Session.ts | 123 +++--- app/src/bridge/components/cast/index.ts | 73 +-- app/src/bridge/components/cast/types.ts | 291 ++++++------ app/src/bridge/components/discovery.ts | 80 ++-- app/src/bridge/components/mediaServer.ts | 68 +-- app/src/bridge/components/receiverSelector.ts | 26 +- app/src/bridge/index.ts | 14 +- app/src/bridge/lib/nativeMessaging.ts | 1 - app/src/bridge/lib/subtitles.ts | 8 +- app/src/bridge/messaging.ts | 192 ++++---- app/src/bridge/types.ts | 13 +- app/src/daemon.ts | 28 +- app/src/global.d.ts | 7 +- app/src/main.ts | 38 +- app/src/transforms.ts | 127 +++--- ext/src/background/ShimManager.ts | 111 ++--- ext/src/background/background.ts | 40 +- ext/src/background/menus.ts | 159 ++++--- ext/src/background/receiverDevices.ts | 74 ++-- .../receiverSelector/ReceiverSelector.ts | 116 ++--- .../ReceiverSelectorManager.ts | 157 ++++--- ext/src/background/receiverSelector/index.ts | 16 +- ext/src/background/whitelist.ts | 120 ++--- ext/src/defaultOptions.ts | 37 +- ext/src/global.d.ts | 61 ++- ext/src/lib/TypedEventTarget.ts | 8 +- ext/src/lib/TypedPort.ts | 35 +- ext/src/lib/TypedStorageArea.ts | 23 +- ext/src/lib/bridge.ts | 135 +++--- ext/src/lib/endpoints.ts | 11 +- ext/src/lib/knownApps.ts | 37 +- ext/src/lib/loadSender.ts | 30 +- ext/src/lib/nativeMessaging.ts | 84 ++-- ext/src/lib/options.ts | 48 +- ext/src/lib/userAgents.ts | 11 +- ext/src/lib/utils.ts | 74 ++-- ext/src/messaging.ts | 237 +++++----- ext/src/senders/media/index.ts | 94 ++-- .../senders/media/overlay/descriptorUtils.ts | 42 +- .../senders/media/overlay/overlayContent.ts | 163 ++++--- .../media/overlay/overlayContentLoader.ts | 13 +- ext/src/senders/mirroring.ts | 111 +++-- ext/src/shim/cast/Session.ts | 207 ++++----- ext/src/shim/cast/dataClasses.ts | 82 ++-- ext/src/shim/cast/enums.ts | 82 ++-- ext/src/shim/cast/index.ts | 189 +++++--- ext/src/shim/cast/media/Media.ts | 417 ++++++++++-------- ext/src/shim/cast/media/dataClasses.ts | 99 ++--- ext/src/shim/cast/media/enums.ts | 162 +++---- ext/src/shim/cast/media/index.ts | 19 +- ext/src/shim/cast/types.ts | 238 +++++----- ext/src/shim/content.ts | 23 +- ext/src/shim/contentBridge.ts | 1 - ext/src/shim/eventMessageChannel.ts | 27 +- ext/src/shim/export.ts | 15 +- ext/src/shim/framework/GoogleCastLauncher.ts | 22 +- .../classes/ActiveInputStateEventData.ts | 5 +- .../framework/classes/ApplicationMetadata.ts | 4 +- .../classes/ApplicationMetadataEventData.ts | 5 +- .../classes/ApplicationStatusEventData.ts | 5 +- ext/src/shim/framework/classes/CastContext.ts | 1 - ext/src/shim/framework/classes/CastOptions.ts | 7 +- ext/src/shim/framework/classes/CastSession.ts | 22 +- .../framework/classes/CastStateEventData.ts | 5 +- ext/src/shim/framework/classes/EventData.ts | 3 +- .../classes/MediaSessionEventData.ts | 5 +- .../shim/framework/classes/RemotePlayer.ts | 11 +- .../classes/RemotePlayerChangedEvent.ts | 5 +- .../classes/RemotePlayerController.ts | 3 +- .../classes/SessionStateEventData.ts | 9 +- .../shim/framework/classes/VolumeEventData.ts | 5 +- ext/src/shim/framework/enums.ts | 84 ++-- ext/src/shim/framework/index.ts | 58 ++- ext/src/shim/index.ts | 8 +- ext/src/shim/types.ts | 1 - ext/src/types.ts | 10 +- 82 files changed, 2683 insertions(+), 2532 deletions(-) diff --git a/.prettierrc.json b/.prettierrc.json index be59270..0ad740f 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,5 +1,6 @@ { "arrowParens": "avoid", "tabWidth": 4, - "trailingComma": "none" + "trailingComma": "none", + "quoteProps": "consistent" } diff --git a/app/@types/bplist-creator/index.d.ts b/app/@types/bplist-creator/index.d.ts index d6710b9..cda2443 100644 --- a/app/@types/bplist-creator/index.d.ts +++ b/app/@types/bplist-creator/index.d.ts @@ -3,13 +3,13 @@ declare module "bplist-creator" { import Buffer from "buffer"; - function bplist (dicts: object): Buffer; + function bplist(dicts: object): Buffer; export = bplist; namespace bplist { export class Real { public value: number; - constructor (value: number); + constructor(value: number); } } } diff --git a/app/@types/bplist-parser/index.d.ts b/app/@types/bplist-parser/index.d.ts index 4eadfe4..26a5ea8 100644 --- a/app/@types/bplist-parser/index.d.ts +++ b/app/@types/bplist-parser/index.d.ts @@ -7,17 +7,16 @@ declare module "bplist-parser" { export var maxObjectCount: number; export class UID { - constructor (id: number); + constructor(id: number); UID: number; } - type ParseFileCallback = ( - err: string - , result?: Buffer) => void; + type ParseFileCallback = (err: string, result?: Buffer) => void; - export function parseFile ( - fileNameOrBuffer: Buffer | string - , callback: ParseFileCallback): void; + export function parseFile( + fileNameOrBuffer: Buffer | string, + callback: ParseFileCallback + ): void; - export function parseBuffer (buffer: Buffer): any; + export function parseBuffer(buffer: Buffer): any; } diff --git a/app/@types/castv2/index.d.ts b/app/@types/castv2/index.d.ts index 1645eff..8866c2c 100644 --- a/app/@types/castv2/index.d.ts +++ b/app/@types/castv2/index.d.ts @@ -10,7 +10,6 @@ declare module "castv2" { type CallbackFunction = () => void; - export interface Channel extends EventEmitter { bus: Client; sourceId: string; @@ -18,51 +17,55 @@ declare module "castv2" { namespace: string; encoding: string; - send (data: any): void; - close (): void; + send(data: any): void; + close(): void; } export interface DeviceAuthMessage { - parse (data: any): any; - serialize (data: any): any; + parse(data: any): any; + serialize(data: any): any; } - export class Client extends EventEmitter { - public connect ( - options: ClientConnectOptions | string - , callback?: CallbackFunction): void; + public connect( + options: ClientConnectOptions | string, + callback?: CallbackFunction + ): void; - public close (): void; + public close(): void; - public send ( - sourceId: string - , destinationId: string - , namespace: string - , data: Buffer | string): void; + public send( + sourceId: string, + destinationId: string, + namespace: string, + data: Buffer | string + ): void; - public createChannel ( - sourceId: string - , destinationId: string - , namespace: string - , encoding: string): Channel; + public createChannel( + sourceId: string, + destinationId: string, + namespace: string, + encoding: string + ): Channel; } export class Server extends EventEmitter { - constructor (options: object); + constructor(options: object); - public listen ( - port: number - , host: string - , callback?: CallbackFunction): void; + public listen( + port: number, + host: string, + callback?: CallbackFunction + ): void; - public send ( - clientId: string - , sourceId: string - , destinationId: string - , namespace: string - , data: Buffer | string): void; + public send( + clientId: string, + sourceId: string, + destinationId: string, + namespace: string, + data: Buffer | string + ): void; - public close (): void; + public close(): void; } } diff --git a/app/@types/fast-srp-hap/index.d.ts b/app/@types/fast-srp-hap/index.d.ts index 134e503..8b277e7 100644 --- a/app/@types/fast-srp-hap/index.d.ts +++ b/app/@types/fast-srp-hap/index.d.ts @@ -12,44 +12,39 @@ declare module "fast-srp-hap" { export const params: { [key: number]: Param }; - type GenKeyCallback = ( - err: string - , buf: Buffer) => void; + type GenKeyCallback = (err: string, buf: Buffer) => void; - export function genKey ( - bytes: number - , callback: GenKeyCallback): void; + export function genKey(bytes: number, callback: GenKeyCallback): void; - export function computeVerifier ( - params: object - , salt: Buffer - , I: Buffer - , P: Buffer): Buffer; + export function computeVerifier( + params: object, + salt: Buffer, + I: Buffer, + P: Buffer + ): Buffer; export class Client { - constructor ( - params: object - , salt_buf: Buffer - , identity_buf: Buffer - , password_buf: Buffer - , secret1_buf: Buffer); + constructor( + params: object, + salt_buf: Buffer, + identity_buf: Buffer, + password_buf: Buffer, + secret1_buf: Buffer + ); - computeA (): Buffer; + computeA(): Buffer; setB(B_buf: Buffer): void; - computeM1 (): Buffer; - checkM2 (serverM2_buf: Buffer): void; - computeK (): Buffer; + computeM1(): Buffer; + checkM2(serverM2_buf: Buffer): void; + computeK(): Buffer; } export class Server { - constructor ( - params: object - , verifier_buf: Buffer - , secret2_buf: Buffer); + constructor(params: object, verifier_buf: Buffer, secret2_buf: Buffer); - computeB (): Buffer; - setA (A_buf: Buffer): void; - checkM1 (clientM1_buf: Buffer): Buffer; - computeK (): Buffer; + computeB(): Buffer; + setA(A_buf: Buffer): void; + checkM1(clientM1_buf: Buffer): Buffer; + computeK(): Buffer; } } diff --git a/app/src/bridge/components/airplay/auth.ts b/app/src/bridge/components/airplay/auth.ts index 438ad4d..d9e9957 100644 --- a/app/src/bridge/components/airplay/auth.ts +++ b/app/src/bridge/components/airplay/auth.ts @@ -14,7 +14,6 @@ import fetch, { Headers } from "node-fetch"; import nacl from "tweetnacl"; import bplist from "./bplist"; - const AIRPLAY_PORT = 7000; const MIMETYPE_BPLIST = "application/x-apple-binary-plist"; @@ -27,10 +26,10 @@ export class AirPlayAuthCredentials { public clientPk: Uint8Array; constructor( - clientId?: string - , clientSk?: Uint8Array - , clientPk?: Uint8Array) { - + clientId?: string, + clientSk?: Uint8Array, + clientPk?: Uint8Array + ) { if (clientId && clientSk && clientPk) { this.clientId = clientId; this.clientSk = clientSk; @@ -74,8 +73,7 @@ export class AirPlayAuth { */ public async finishPairing(pin: string) { // Stage 1 response - const { pk: serverPk - , salt: serverSalt } = await this.pairSetupPin1(); + const { pk: serverPk, salt: serverSalt } = await this.pairSetupPin1(); // SRP params must 2048-bit SHA1 const srpParams = srp6a.params[2048]; @@ -83,19 +81,21 @@ export class AirPlayAuth { // Create SRP client const srpClient = new srp6a.Client( - srpParams // Params - , serverSalt // Receiver salt - , Buffer.from(this.credentials.clientId) // Username - , Buffer.from(pin) // Password (receiver pin) - , Buffer.from(this.credentials.clientSk)); // Client secret key + srpParams, // Params + serverSalt, // Receiver salt + Buffer.from(this.credentials.clientId), // Username + Buffer.from(pin), // Password (receiver pin) + Buffer.from(this.credentials.clientSk) // Client secret key + ); // Add receiver's public key srpClient.setB(serverPk); // Stage 2 response await this.pairSetupPin2( - srpClient.computeA() // SRP public key - , srpClient.computeM1()); // SRP proof + srpClient.computeA(), // SRP public key + srpClient.computeM1() // SRP proof + ); // Stage 3 response await this.pairSetupPin3(srpClient.computeK()); @@ -108,12 +108,10 @@ export class AirPlayAuth { * its public key / salt. */ public async pairSetupPin1(): Promise { - const [ response ] = await this.sendPostRequestBplist( - "/pair-setup-pin" - , { - method: "pin" - , user: this.credentials.clientId - }); + const [response] = await this.sendPostRequestBplist("/pair-setup-pin", { + method: "pin", + user: this.credentials.clientId + }); return response; } @@ -125,13 +123,11 @@ export class AirPlayAuth { * public keys, sending them to the receiver and receiving its * proof. */ - public async pairSetupPin2( - pk: Buffer - , proof: Buffer): Promise { - - const [ response ] = await this.sendPostRequestBplist( - "/pair-setup-pin" - , { pk, proof }); + public async pairSetupPin2(pk: Buffer, proof: Buffer): Promise { + const [response] = await this.sendPostRequestBplist("/pair-setup-pin", { + pk, + proof + }); return response; } @@ -144,17 +140,19 @@ export class AirPlayAuth { * responds confirming the pairing is complete. */ public async pairSetupPin3( - sharedSecretHash: crypto.BinaryLike): Promise { - + sharedSecretHash: crypto.BinaryLike + ): Promise { // Create AES key - const aesKey = crypto.createHash("sha512") + const aesKey = crypto + .createHash("sha512") .update("Pair-Setup-AES-Key") .update(sharedSecretHash) .digest() .slice(0, 16); // Create AES IV - const aesIv = crypto.createHash("sha512") + const aesIv = crypto + .createHash("sha512") .update("Pair-Setup-AES-IV") .update(sharedSecretHash) .digest() @@ -162,7 +160,6 @@ export class AirPlayAuth { aesIv[15]++; - const cipher = crypto.createCipheriv("aes-128-gcm", aesKey, aesIv); // Encode client public key @@ -170,23 +167,23 @@ export class AirPlayAuth { cipher.final(); const authTag = cipher.getAuthTag(); - const [ response ] = await this.sendPostRequestBplist( - "/pair-setup-pin" - , { epk, authTag }); + const [response] = await this.sendPostRequestBplist("/pair-setup-pin", { + epk, + authTag + }); return response; } - /** * Sends a POST request to receiver and returns the * response. */ public async sendPostRequest( - path: string - , contentType?: string - , data?: Buffer | string): Promise { - + path: string, + contentType?: string, + data?: Buffer | string + ): Promise { // Create URL from base receiver URL and path const requestUrl = new URL(path, this.baseUrl); @@ -200,9 +197,9 @@ export class AirPlayAuth { } const response = await fetch(requestUrl.href, { - method: "POST" - , headers: requestHeaders - , body: data + method: "POST", + headers: requestHeaders, + body: data }); if (!response.ok) { @@ -217,16 +214,17 @@ export class AirPlayAuth { * receiver, then decodes and returns the response. */ public async sendPostRequestBplist( - path: string - , data?: object): Promise { - + path: string, + data?: object + ): Promise { // Convert data to compatible type - const requestBody = data - ? bplist.create(data) - : undefined; + const requestBody = data ? bplist.create(data) : undefined; const response = await this.sendPostRequest( - path, MIMETYPE_BPLIST, requestBody); + path, + MIMETYPE_BPLIST, + requestBody + ); // Convert response data to Buffer for bplist-parser return bplist.parse.parseBuffer(response); diff --git a/app/src/bridge/components/cast/Session.ts b/app/src/bridge/components/cast/Session.ts index b6cbcda..3a1ed99 100644 --- a/app/src/bridge/components/cast/Session.ts +++ b/app/src/bridge/components/cast/Session.ts @@ -7,14 +7,12 @@ import { sendMessage } from "../../lib/nativeMessaging"; import { ReceiverDevice } from "../../types"; import { ReceiverApplication, ReceiverMessage, SenderMessage } from "./types"; - export const NS_CONNECTION = "urn:x-cast:com.google.cast.tp.connection"; export const NS_HEARTBEAT = "urn:x-cast:com.google.cast.tp.heartbeat"; export const NS_RECEIVER = "urn:x-cast:com.google.cast.receiver"; const HEARTBEAT_INTERVAL = 5000; - class CastClient { protected client = new Client(); @@ -22,18 +20,26 @@ class CastClient { protected heartbeatChannel?: Channel; protected heartbeatIntervalId?: NodeJS.Timeout; - constructor(protected sourceId = "sender-0" - , protected destinationId = "receiver-0") {} + constructor( + protected sourceId = "sender-0", + protected destinationId = "receiver-0" + ) {} /** * Create a channel on the client connection with a given * namespace. */ - createChannel(namespace: string - , sourceId = this.sourceId - , destinationId = this.destinationId) { - - return this.client.createChannel(sourceId, destinationId, namespace, "JSON"); + createChannel( + namespace: string, + sourceId = this.sourceId, + destinationId = this.destinationId + ) { + return this.client.createChannel( + sourceId, + destinationId, + namespace, + "JSON" + ); } connect(host: string, port: number, onHeartbeat?: () => void) { @@ -49,10 +55,10 @@ class CastClient { this.client.connect({ host, port }, () => { this.connectionChannel = this.createChannel(NS_CONNECTION); this.heartbeatChannel = this.createChannel(NS_HEARTBEAT); - + this.connectionChannel.send({ type: "CONNECT" }); this.heartbeatChannel.send({ type: "PING" }); - + this.heartbeatIntervalId = setInterval(() => { this.heartbeatChannel?.send({ type: "PING" }); if (onHeartbeat) { @@ -66,7 +72,6 @@ class CastClient { } } - type OnSessionCreatedCallback = (sessionId: string) => void; export default class Session extends CastClient { @@ -81,7 +86,7 @@ export default class Session extends CastClient { private transportId?: string; private transportConnection?: Channel; private transportHeartbeat?: Channel; - + // Channels created by `sendCastSessionMessage` messages private namespaceChannelMap = new Map(); @@ -93,12 +98,17 @@ export default class Session extends CastClient { private onSessionCreated?: OnSessionCreatedCallback; - private establishAppConnection(transportId: string) { this.transportConnection = this.createChannel( - NS_CONNECTION, this.sourceId, transportId); + NS_CONNECTION, + this.sourceId, + transportId + ); this.transportHeartbeat = this.createChannel( - NS_HEARTBEAT, this.sourceId, transportId); + NS_HEARTBEAT, + this.sourceId, + transportId + ); this.transportConnection.send({ type: "CONNECT" }); } @@ -111,7 +121,8 @@ export default class Session extends CastClient { case "RECEIVER_STATUS": { const { status } = message; const application = status.applications?.find( - app => app.appId === this.appId); + app => app.appId === this.appId + ); /** * If application isn't set, still waiting on the launch @@ -133,20 +144,20 @@ export default class Session extends CastClient { const { friendlyName } = this.receiverDevice; sendMessage({ - subject: "shim:castSessionCreated" - , data: { - sessionId: this.sessionId - , statusText: application.statusText - , namespaces: application.namespaces - , volume: status.volume - , appId: application.appId - , displayName: application.displayName - , receiverFriendlyName: friendlyName - , transportId: this.sessionId + subject: "shim:castSessionCreated", + data: { + sessionId: this.sessionId, + statusText: application.statusText, + namespaces: application.namespaces, + volume: status.volume, + appId: application.appId, + displayName: application.displayName, + receiverFriendlyName: friendlyName, + transportId: this.sessionId, - // TODO: Fix this - , senderApps: [] - , appImages: [] + // TODO: Fix this + senderApps: [], + appImages: [] } }); } @@ -161,15 +172,15 @@ export default class Session extends CastClient { } sendMessage({ - subject: "shim:castSessionUpdated" - , data: { - sessionId: this.sessionId - , statusText: application.statusText - , namespaces: application.namespaces - , volume: message.status.volume + subject: "shim:castSessionUpdated", + data: { + sessionId: this.sessionId, + statusText: application.statusText, + namespaces: application.namespaces, + volume: message.status.volume } }); - + break; } @@ -179,13 +190,16 @@ export default class Session extends CastClient { break; } } - } + }; sendMessage(namespace: string, message: unknown) { let channel = this.namespaceChannelMap.get(namespace); if (!channel) { channel = this.createChannel( - namespace, this.sourceId, this.transportId); + namespace, + this.sourceId, + this.transportId + ); channel.on("message", messageData => { if (!this.sessionId) { @@ -195,11 +209,11 @@ export default class Session extends CastClient { messageData = JSON.stringify(messageData); sendMessage({ - subject: "shim:receivedCastSessionMessage" - , data: { - sessionId: this.sessionId - , namespace - , messageData + subject: "shim:receivedCastSessionMessage", + data: { + sessionId: this.sessionId, + namespace, + messageData } }); }); @@ -222,25 +236,24 @@ export default class Session extends CastClient { return requestId; } - constructor(public appId: string - , public receiverDevice: ReceiverDevice) { - + constructor(public appId: string, public receiverDevice: ReceiverDevice) { super(); this.client.on("close", () => { if (this.sessionId) { sendMessage({ - subject: "shim:castSessionStopped" - , data: { sessionId: this.sessionId } + subject: "shim:castSessionStopped", + data: { sessionId: this.sessionId } }); } }); } - async connect(host: string - , port: number - , onSessionCreated?: OnSessionCreatedCallback) { - + async connect( + host: string, + port: number, + onSessionCreated?: OnSessionCreatedCallback + ) { if (onSessionCreated) { this.onSessionCreated = onSessionCreated; } @@ -253,8 +266,8 @@ export default class Session extends CastClient { }); this.launchRequestId = this.sendReceiverMessage({ - type: "LAUNCH" - , appId: this.appId + type: "LAUNCH", + appId: this.appId }); } } diff --git a/app/src/bridge/components/cast/index.ts b/app/src/bridge/components/cast/index.ts index cf27e8e..da8b394 100644 --- a/app/src/bridge/components/cast/index.ts +++ b/app/src/bridge/components/cast/index.ts @@ -5,9 +5,7 @@ import castv2 from "castv2"; import { sendMessage } from "../../lib/nativeMessaging"; import { Message } from "../../messaging"; -import Session, { NS_CONNECTION - , NS_RECEIVER } from "./Session"; - +import Session, { NS_CONNECTION, NS_RECEIVER } from "./Session"; const sessions = new Map(); @@ -19,9 +17,12 @@ export function handleCastMessage(message: Message) { // Connect and store with returned ID const session = new Session(appId, receiverDevice); session.connect( - receiverDevice.host, receiverDevice.port, sessionId => { - sessions.set(sessionId, session); - }); + receiverDevice.host, + receiverDevice.port, + sessionId => { + sessions.set(sessionId, session); + } + ); break; } @@ -32,10 +33,11 @@ export function handleCastMessage(message: Message) { const session = sessions.get(sessionId); if (!session) { sendMessage({ - subject: "shim:impl_sendCastMessage" - , data: { - error: "Session does not exist" - , sessionId, messageId + subject: "shim:impl_sendCastMessage", + data: { + error: "Session does not exist", + sessionId, + messageId } }); @@ -46,10 +48,11 @@ export function handleCastMessage(message: Message) { session.sendReceiverMessage(messageData); } catch (err) { sendMessage({ - subject: "shim:impl_sendCastMessage" - , data: { - error: `Failed to send message (${err})` - , sessionId, messageId + subject: "shim:impl_sendCastMessage", + data: { + error: `Failed to send message (${err})`, + sessionId, + messageId } }); @@ -58,8 +61,8 @@ export function handleCastMessage(message: Message) { // Success sendMessage({ - subject: "shim:impl_sendCastMessage" - , data: { sessionId, messageId } + subject: "shim:impl_sendCastMessage", + data: { sessionId, messageId } }); break; @@ -71,10 +74,11 @@ export function handleCastMessage(message: Message) { const session = sessions.get(sessionId); if (!session) { sendMessage({ - subject: "shim:impl_sendCastMessage" - , data: { - error: "Session does not exist" - , sessionId, messageId + subject: "shim:impl_sendCastMessage", + data: { + error: "Session does not exist", + sessionId, + messageId } }); @@ -91,10 +95,11 @@ export function handleCastMessage(message: Message) { session.sendMessage(namespace, messageData); } catch (err) { sendMessage({ - subject: "shim:impl_sendCastMessage" - , data: { - error: `Failed to send message (${err})` - , sessionId, messageId + subject: "shim:impl_sendCastMessage", + data: { + error: `Failed to send message (${err})`, + sessionId, + messageId } }); @@ -103,8 +108,8 @@ export function handleCastMessage(message: Message) { // Success sendMessage({ - subject: "shim:impl_sendCastMessage" - , data: { sessionId, messageId } + subject: "shim:impl_sendCastMessage", + data: { sessionId, messageId } }); break; @@ -117,12 +122,20 @@ export function handleCastMessage(message: Message) { client.connect({ host, port }, () => { const sourceId = "sender-0"; const destinationId = "receiver-0"; - + const clientConnection = client.createChannel( - sourceId, destinationId, NS_CONNECTION, "JSON"); + sourceId, + destinationId, + NS_CONNECTION, + "JSON" + ); const clientReceiver = client.createChannel( - sourceId, destinationId, NS_RECEIVER, "JSON"); - + sourceId, + destinationId, + NS_RECEIVER, + "JSON" + ); + clientConnection.send({ type: "CONNECT" }); clientReceiver.send({ type: "STOP", requestId: 1 }); }); diff --git a/app/src/bridge/components/cast/types.ts b/app/src/bridge/components/cast/types.ts index deb0f07..0b4ac1e 100644 --- a/app/src/bridge/components/cast/types.ts +++ b/app/src/bridge/components/cast/types.ts @@ -7,18 +7,18 @@ export interface Image { } enum Capability { - VIDEO_OUT = "video_out" - , AUDIO_OUT = "audio_out" - , VIDEO_IN = "video_in" - , AUDIO_IN = "audio_in" - , MULTIZONE_GROUP = "multizone_group" + VIDEO_OUT = "video_out", + AUDIO_OUT = "audio_out", + VIDEO_IN = "video_in", + AUDIO_IN = "audio_in", + MULTIZONE_GROUP = "multizone_group" } enum ReceiverType { - CAST = "cast" - , DIAL = "dial" - , HANGOUT = "hangout" - , CUSTOM = "custom" + CAST = "cast", + DIAL = "dial", + HANGOUT = "hangout", + CUSTOM = "custom" } export interface SenderApplication { @@ -28,9 +28,9 @@ export interface SenderApplication { } enum VolumeControlType { - ATTENUATION = "attenuation" - , FIXED = "fixed" - , MASTER = "master" + ATTENUATION = "attenuation", + FIXED = "fixed", + MASTER = "master" } export interface Volume { @@ -43,75 +43,74 @@ export interface Volume { // Media enum IdleReason { - CANCELLED = "CANCELLED" - , INTERRUPTED = "INTERRUPTED" - , FINISHED = "FINISHED" - , ERROR = "ERROR" + CANCELLED = "CANCELLED", + INTERRUPTED = "INTERRUPTED", + FINISHED = "FINISHED", + ERROR = "ERROR" } enum HlsSegmentFormat { - AAC = "aac" - , AC3 = "ac3" - , MP3 = "mp3" - , TS = "ts" - , TS_AAC = "ts_aac" - , E_AC3 = "e_ac3" - , FMP4 = "fmp4" + AAC = "aac", + AC3 = "ac3", + MP3 = "mp3", + TS = "ts", + TS_AAC = "ts_aac", + E_AC3 = "e_ac3", + FMP4 = "fmp4" } export enum HlsVideoSegmentFormat { - MPEG2_TS = "mpeg2_ts" - , FMP4 = "fmp4" + MPEG2_TS = "mpeg2_ts", + FMP4 = "fmp4" } enum MetadataType { - GENERIC - , MOVIE - , TV_SHOW - , MUSIC_TRACK - , PHOTO - , AUDIOBOOK_CHAPTER + GENERIC, + MOVIE, + TV_SHOW, + MUSIC_TRACK, + PHOTO, + AUDIOBOOK_CHAPTER } enum PlayerState { - IDLE = "IDLE" - , PLAYING = "PLAYING" - , PAUSED = "PAUSED" - , BUFFERING = "BUFFERING" + IDLE = "IDLE", + PLAYING = "PLAYING", + PAUSED = "PAUSED", + BUFFERING = "BUFFERING" } enum RepeatMode { - OFF = "REPEAT_OFF" - , ALL = "REPEAT_ALL" - , SINGLE = "REPEAT_SINGLE" - , ALL_AND_SHUFFLE = "REPEAT_ALL_AND_SHUFFLE" + OFF = "REPEAT_OFF", + ALL = "REPEAT_ALL", + SINGLE = "REPEAT_SINGLE", + ALL_AND_SHUFFLE = "REPEAT_ALL_AND_SHUFFLE" } enum ResumeState { - PLAYBACK_START = "PLAYBACK_START" - , PLAYBACK_PAUSE = "PLAYBACK_PAUSE" + PLAYBACK_START = "PLAYBACK_START", + PLAYBACK_PAUSE = "PLAYBACK_PAUSE" } enum StreamType { - BUFFERED = "BUFFERED" - , LIVE = "LIVE" - , OTHER = "OTHER" + BUFFERED = "BUFFERED", + LIVE = "LIVE", + OTHER = "OTHER" } enum TrackType { - TEXT = "TEXT" - , AUDIO = "AUDIO" - , VIDEO = "VIDEO" + TEXT = "TEXT", + AUDIO = "AUDIO", + VIDEO = "VIDEO" } export enum UserAction { - LIKE = "LIKE" - , DISLIKE = "DISLIKE" - , FOLLOW = "FOLLOW" - , UNFOLLOW = "UNFOLLOW" + LIKE = "LIKE", + DISLIKE = "DISLIKE", + FOLLOW = "FOLLOW", + UNFOLLOW = "UNFOLLOW" } - interface Break { breakClipIds: string[]; duration?: number; @@ -173,11 +172,11 @@ interface VastAdsRequest { } type Metadata = - GenericMediaMetadata - | MovieMediaMetadata - | MusicTrackMediaMetadata - | PhotoMediaMetadata - | TvShowMediaMetadata; + | GenericMediaMetadata + | MovieMediaMetadata + | MusicTrackMediaMetadata + | PhotoMediaMetadata + | TvShowMediaMetadata; interface MediaInformation { atvEntity?: string; @@ -284,11 +283,11 @@ export interface MediaStatus { playbackRate: number; playerState: PlayerState; idleReason?: IdleReason; - items?: QueueItem[] + items?: QueueItem[]; currentTime: number; supportedMediaCommands: number; repeatMode: RepeatMode; - volume: Volume + volume: Volume; customData: unknown; } @@ -329,23 +328,21 @@ export interface ReceiverStatus { volume: Volume; } - interface ReqBase { requestId: number; } // NS: urn:x-cast:com.google.cast.receiver export type SenderMessage = - ReqBase & { type: "LAUNCH", appId: string } - | ReqBase & { type: "STOP", sessionId: string } - | ReqBase & { type: "GET_STATUS" } - | ReqBase & { type: "GET_APP_AVAILABILITY", appId: string[] } - | ReqBase & { type: "SET_VOLUME", volume: Volume }; + | (ReqBase & { type: "LAUNCH"; appId: string }) + | (ReqBase & { type: "STOP"; sessionId: string }) + | (ReqBase & { type: "GET_STATUS" }) + | (ReqBase & { type: "GET_APP_AVAILABILITY"; appId: string[] }) + | (ReqBase & { type: "SET_VOLUME"; volume: Volume }); export type ReceiverMessage = - ReqBase & { type: "RECEIVER_STATUS", status: ReceiverStatus } - | ReqBase & { type: "LAUNCH_ERROR", reason: string } - + | (ReqBase & { type: "RECEIVER_STATUS"; status: ReceiverStatus }) + | (ReqBase & { type: "LAUNCH_ERROR"; reason: string }); interface MediaReqBase extends ReqBase { mediaSessionId: number; @@ -354,84 +351,84 @@ interface MediaReqBase extends ReqBase { // NS: urn:x-cast:com.google.cast.media export type SenderMediaMessage = - | MediaReqBase & { type: "PLAY" } - | MediaReqBase & { type: "PAUSE" } - | MediaReqBase & { type: "MEDIA_GET_STATUS" } - | MediaReqBase & { type: "STOP" } - | MediaReqBase & { type: "MEDIA_SET_VOLUME", volume: Volume } - | MediaReqBase & { type: "SET_PLAYBACK_RATE" , playbackRate: number } - | ReqBase & { - type: "LOAD" - , activeTrackIds: Nullable - , atvCredentials?: string - , atvCredentialsType?: string - , autoplay: Nullable - , currentTime: Nullable - , customData?: unknown - , media: MediaInformation - , sessionId: Nullable - } - | MediaReqBase & { - type: "SEEK" - , resumeState: Nullable - , currentTime: Nullable - } - | MediaReqBase & { - type: "EDIT_TRACKS_INFO" - , activeTrackIds: Nullable - , textTrackStyle: Nullable - } - // QueueLoadRequest - | MediaReqBase & { - type: "QUEUE_LOAD" - , items: QueueItem[] - , startIndex: number - , repeatMode: string - , sessionId: Nullable - } - // QueueInsertItemsRequest - | MediaReqBase & { - type: "QUEUE_INSERT" - , items: QueueItem[] - , insertBefore: Nullable - , sessionId: Nullable - } - // QueueUpdateItemsRequest - | MediaReqBase & { - type: "QUEUE_UPDATE" - , items: QueueItem[] - , sessionId: Nullable - } - // QueueJumpRequest - | MediaReqBase & { - type: "QUEUE_UPDATE" - , jump: Nullable - , currentItemId: Nullable - , sessionId: Nullable - } - // QueueRemoveItemsRequest - | MediaReqBase & { - type: "QUEUE_REMOVE" - , itemIds: number[] - , sessionId: Nullable - } - // QueueReorderItemsRequest - | MediaReqBase & { - type: "QUEUE_REORDER" - , itemIds: number[] - , insertBefore: Nullable - , sessionId: Nullable - } - // QueueSetPropertiesRequest - | MediaReqBase & { - type: "QUEUE_UPDATE" - , repeatMode: Nullable - , sessionId: Nullable - }; + | (MediaReqBase & { type: "PLAY" }) + | (MediaReqBase & { type: "PAUSE" }) + | (MediaReqBase & { type: "MEDIA_GET_STATUS" }) + | (MediaReqBase & { type: "STOP" }) + | (MediaReqBase & { type: "MEDIA_SET_VOLUME"; volume: Volume }) + | (MediaReqBase & { type: "SET_PLAYBACK_RATE"; playbackRate: number }) + | (ReqBase & { + type: "LOAD"; + activeTrackIds: Nullable; + atvCredentials?: string; + atvCredentialsType?: string; + autoplay: Nullable; + currentTime: Nullable; + customData?: unknown; + media: MediaInformation; + sessionId: Nullable; + }) + | (MediaReqBase & { + type: "SEEK"; + resumeState: Nullable; + currentTime: Nullable; + }) + | (MediaReqBase & { + type: "EDIT_TRACKS_INFO"; + activeTrackIds: Nullable; + textTrackStyle: Nullable; + }) + // QueueLoadRequest + | (MediaReqBase & { + type: "QUEUE_LOAD"; + items: QueueItem[]; + startIndex: number; + repeatMode: string; + sessionId: Nullable; + }) + // QueueInsertItemsRequest + | (MediaReqBase & { + type: "QUEUE_INSERT"; + items: QueueItem[]; + insertBefore: Nullable; + sessionId: Nullable; + }) + // QueueUpdateItemsRequest + | (MediaReqBase & { + type: "QUEUE_UPDATE"; + items: QueueItem[]; + sessionId: Nullable; + }) + // QueueJumpRequest + | (MediaReqBase & { + type: "QUEUE_UPDATE"; + jump: Nullable; + currentItemId: Nullable; + sessionId: Nullable; + }) + // QueueRemoveItemsRequest + | (MediaReqBase & { + type: "QUEUE_REMOVE"; + itemIds: number[]; + sessionId: Nullable; + }) + // QueueReorderItemsRequest + | (MediaReqBase & { + type: "QUEUE_REORDER"; + itemIds: number[]; + insertBefore: Nullable; + sessionId: Nullable; + }) + // QueueSetPropertiesRequest + | (MediaReqBase & { + type: "QUEUE_UPDATE"; + repeatMode: Nullable; + sessionId: Nullable; + }); export type ReceiverMediaMessage = - MediaReqBase & { type: "MEDIA_STATUS", status: MediaStatus[] } - | MediaReqBase & { type: "INVALID_PLAYER_STATE" } - | MediaReqBase & { type: "LOAD_FAILED" } - | MediaReqBase & { type: "LOAD_CANCELLED" } - | MediaReqBase & { type: "INVALID_REQUEST" }; + | (MediaReqBase & { type: "MEDIA_STATUS"; status: MediaStatus[] }) + | (MediaReqBase & { type: "INVALID_PLAYER_STATE" }) + | (MediaReqBase & { type: "LOAD_FAILED" }) + | (MediaReqBase & { type: "LOAD_CANCELLED" }) + | (MediaReqBase & { type: "INVALID_REQUEST" }); diff --git a/app/src/bridge/components/discovery.ts b/app/src/bridge/components/discovery.ts index b10108c..8842313 100644 --- a/app/src/bridge/components/discovery.ts +++ b/app/src/bridge/components/discovery.ts @@ -9,25 +9,31 @@ import mdns from "mdns"; import { sendMessage } from "../lib/nativeMessaging"; import { ReceiverStatus } from "./cast/types"; -import { NS_CONNECTION, NS_HEARTBEAT, NS_RECEIVER } - from "./cast/Session"; - +import { NS_CONNECTION, NS_HEARTBEAT, NS_RECEIVER } from "./cast/Session"; interface CastTxtRecord { - id: string; cd: string; rm: string; - ve: string; md: string; ic: string; - fn: string; ca: string; st: string; - bs: string; nf: string; rs: string; + id: string; + cd: string; + rm: string; + ve: string; + md: string; + ic: string; + fn: string; + ca: string; + st: string; + bs: string; + nf: string; + rs: string; } const browser = mdns.createBrowser(mdns.tcp("googlecast"), { resolverSequence: [ - mdns.rst.DNSServiceResolve() - , "DNSServiceGetAddrInfo" in mdns.dns_sd + mdns.rst.DNSServiceResolve(), + "DNSServiceGetAddrInfo" in mdns.dns_sd ? mdns.rst.DNSServiceGetAddrInfo() - // Some issues on Linux with IPv6, so restrict to IPv4 - : mdns.rst.getaddrinfo({ families: [ 4 ]}) - , mdns.rst.makeAddressesUnique() + : // Some issues on Linux with IPv6, so restrict to IPv4 + mdns.rst.getaddrinfo({ families: [4] }), + mdns.rst.makeAddressesUnique() ] }); @@ -39,13 +45,13 @@ function onBrowserServiceUp(service: mdns.Service) { const txtRecord = service.txtRecord as CastTxtRecord; sendMessage({ - subject: "main:receiverDeviceUp" - , data: { + subject: "main:receiverDeviceUp", + data: { receiverDevice: { - host: service.addresses[0] - , port: service.port - , id: service.name - , friendlyName: txtRecord.fn + host: service.addresses[0], + port: service.port, + id: service.name, + friendlyName: txtRecord.fn } } }); @@ -59,15 +65,14 @@ function onBrowserServiceDown(service: mdns.Service) { const txtRecord = service.txtRecord as CastTxtRecord; sendMessage({ - subject: "main:receiverDeviceDown" - , data: { receiverDeviceId: service.name } + subject: "main:receiverDeviceDown", + data: { receiverDeviceId: service.name } }); } browser.on("serviceUp", onBrowserServiceUp); browser.on("serviceDown", onBrowserServiceDown); - interface InitializeOptions { shouldWatchStatus?: boolean; } @@ -88,8 +93,7 @@ export function startDiscovery(options: InitializeOptions) { return; } - const listener = new StatusListener( - service.addresses[0], service.port); + const listener = new StatusListener(service.addresses[0], service.port); listener.on("receiverStatus", (status: ReceiverStatus) => { if (!service.name) { @@ -97,10 +101,10 @@ export function startDiscovery(options: InitializeOptions) { } sendMessage({ - subject: "main:receiverDeviceUpdated" - , data: { - receiverDeviceId: service.name - , status + subject: "main:receiverDeviceUpdated", + data: { + receiverDeviceId: service.name, + status } }); }); @@ -122,12 +126,11 @@ export function stopDiscovery() { browser.stop(); } - /** * Creates a connection to a receiver device and forwards * RECEIVER_STATUS updates to the extension. */ - export default class StatusListener extends EventEmitter { +export default class StatusListener extends EventEmitter { private client: Client; private clientReceiver?: Channel; private clientHeartbeatIntervalId?: NodeJS.Timeout; @@ -160,17 +163,28 @@ export function stopDiscovery() { this.client.close(); } - private onConnect(): void { const sourceId = "sender-0"; const destinationId = "receiver-0"; const clientConnection = this.client.createChannel( - sourceId, destinationId, NS_CONNECTION, "JSON"); + sourceId, + destinationId, + NS_CONNECTION, + "JSON" + ); const clientHeartbeat = this.client.createChannel( - sourceId, destinationId, NS_HEARTBEAT, "JSON"); + sourceId, + destinationId, + NS_HEARTBEAT, + "JSON" + ); const clientReceiver = this.client.createChannel( - sourceId, destinationId, NS_RECEIVER, "JSON"); + sourceId, + destinationId, + NS_RECEIVER, + "JSON" + ); clientReceiver.on("message", data => { switch (data.type) { diff --git a/app/src/bridge/components/mediaServer.ts b/app/src/bridge/components/mediaServer.ts index 8a7f807..5fb1921 100644 --- a/app/src/bridge/components/mediaServer.ts +++ b/app/src/bridge/components/mediaServer.ts @@ -11,7 +11,6 @@ import mime from "mime-types"; import { sendMessage } from "../lib/nativeMessaging"; import { convertSrtToVtt } from "../lib/subtitles"; - export let mediaServer: http.Server | undefined; export async function startMediaServer(filePath: string, port: number) { @@ -41,7 +40,7 @@ export async function startMediaServer(filePath: string, port: number) { } catch (err) { console.error("Error: Failed to find media path."); sendMessage({ - subject: "mediaCast:mediaServerError" + subject: "mediaCast:mediaServerError" }); return; @@ -63,15 +62,19 @@ export async function startMediaServer(filePath: string, port: number) { */ const subtitles = new Map(); try { - const dirEntries = await fs.promises.readdir( - fileDir, { withFileTypes: true }); + const dirEntries = await fs.promises.readdir(fileDir, { + withFileTypes: true + }); for (const dirEntry of dirEntries) { - if (dirEntry.isFile() - && mime.lookup(dirEntry.name) === "application/x-subrip") { - - subtitles.set(dirEntry.name, await convertSrtToVtt( - path.join(fileDir, dirEntry.name))); + if ( + dirEntry.isFile() && + mime.lookup(dirEntry.name) === "application/x-subrip" + ) { + subtitles.set( + dirEntry.name, + await convertSrtToVtt(path.join(fileDir, dirEntry.name)) + ); } } } catch (err) { @@ -96,22 +99,20 @@ export async function startMediaServer(filePath: string, port: number) { if (range) { const bounds = range.substring(6).split("-"); const start = parseInt(bounds[0]); - const end = bounds[1] - ? parseInt(bounds[1]) : fileSize - 1; + const end = bounds[1] ? parseInt(bounds[1]) : fileSize - 1; res.writeHead(206, { - "Accept-Ranges": "bytes" - , "Content-Range": `bytes ${start}-${end}/${fileSize}` - , "Content-Length": (end - start) + 1 - , "Content-Type": contentType + "Accept-Ranges": "bytes", + "Content-Range": `bytes ${start}-${end}/${fileSize}`, + "Content-Length": end - start + 1, + "Content-Type": contentType }); - fs.createReadStream( - filePath, { start, end }).pipe(res); + fs.createReadStream(filePath, { start, end }).pipe(res); } else { res.writeHead(200, { - "Content-Length": fileSize - , "Content-Type": contentType + "Content-Length": fileSize, + "Content-Type": contentType }); fs.createReadStream(filePath).pipe(res); @@ -139,7 +140,8 @@ export async function startMediaServer(filePath: string, port: number) { const ifaces = Object.values(os.networkInterfaces()); for (const iface of ifaces) { const matchingIface = iface?.find( - details => details.family === "IPv4" && !details.internal); + details => details.family === "IPv4" && !details.internal + ); if (matchingIface) { localAddress = matchingIface.address; } @@ -155,21 +157,25 @@ export async function startMediaServer(filePath: string, port: number) { } sendMessage({ - subject: "mediaCast:mediaServerStarted" - , data: { - mediaPath: fileName - , subtitlePaths: Array.from(subtitles.keys()) - , localAddress + subject: "mediaCast:mediaServerStarted", + data: { + mediaPath: fileName, + subtitlePaths: Array.from(subtitles.keys()), + localAddress } }); }); - mediaServer.on("close", () => sendMessage({ - subject: "mediaCast:mediaServerStopped" - })); - mediaServer.on("error", () => sendMessage({ - subject: "mediaCast:mediaServerError" - })); + mediaServer.on("close", () => + sendMessage({ + subject: "mediaCast:mediaServerStopped" + }) + ); + mediaServer.on("error", () => + sendMessage({ + subject: "mediaCast:mediaServerError" + }) + ); mediaServer.listen(port); } diff --git a/app/src/bridge/components/receiverSelector.ts b/app/src/bridge/components/receiverSelector.ts index 0357129..8ed78b7 100644 --- a/app/src/bridge/components/receiverSelector.ts +++ b/app/src/bridge/components/receiverSelector.ts @@ -5,13 +5,11 @@ import path from "path"; import { sendMessage } from "../lib/nativeMessaging"; - function fatal(message: string) { console.error(message); process.exit(1); } - let selectorApp: child_process.ChildProcess | undefined; let selectorAppOpen = false; @@ -35,37 +33,39 @@ export function startReceiverSelector(data: string) { selectorAppOpen = false; } - const selectorPath = path.join(process.cwd() - , "fx_cast_selector.app/Contents/MacOS/fx_cast_selector"); - - selectorApp = child_process.spawn(selectorPath, [ data ]); + const selectorPath = path.join( + process.cwd(), + "fx_cast_selector.app/Contents/MacOS/fx_cast_selector" + ); + + selectorApp = child_process.spawn(selectorPath, [data]); selectorAppOpen = true; if (selectorApp.stdout) { - selectorApp.stdout.setEncoding("utf-8"); + selectorApp.stdout.setEncoding("utf-8"); selectorApp.stdout.on("data", data => { const jsonData = JSON.parse(data); if (!jsonData.mediaType) { sendMessage({ - subject: "main:receiverSelector/stopped" - , data: jsonData + subject: "main:receiverSelector/stopped", + data: jsonData }); return; } sendMessage({ - subject: "main:receiverSelector/selected" - , data: jsonData + subject: "main:receiverSelector/selected", + data: jsonData }); }); } selectorApp.on("error", err => { sendMessage({ - subject: "main:receiverSelector/error" - , data: err.message + subject: "main:receiverSelector/error", + data: err.message }); }); diff --git a/app/src/bridge/index.ts b/app/src/bridge/index.ts index 4c6cd52..82e5571 100755 --- a/app/src/bridge/index.ts +++ b/app/src/bridge/index.ts @@ -6,19 +6,19 @@ import { Message } from "./messaging"; import { handleCastMessage } from "./components/cast"; import { startDiscovery, stopDiscovery } from "./components/discovery"; import { startMediaServer, stopMediaServer } from "./components/mediaServer"; -import { startReceiverSelector, stopReceiverSelector } - from "./components/receiverSelector"; +import { + startReceiverSelector, + stopReceiverSelector +} from "./components/receiverSelector"; import { __applicationName, __applicationVersion } from "../../package.json"; - process.on("SIGTERM", () => { stopDiscovery(); stopMediaServer(); stopReceiverSelector(); }); - /** * Handle incoming messages from the extension and forward * them to the appropriate handlers. @@ -41,10 +41,12 @@ decodeTransform.on("data", (message: Message) => { // Receiver selector case "bridge:openReceiverSelector": { - startReceiverSelector(message.data); break; + startReceiverSelector(message.data); + break; } case "bridge:closeReceiverSelector": { - stopReceiverSelector(); break; + stopReceiverSelector(); + break; } // Media server diff --git a/app/src/bridge/lib/nativeMessaging.ts b/app/src/bridge/lib/nativeMessaging.ts index 9b1a755..d0ed148 100644 --- a/app/src/bridge/lib/nativeMessaging.ts +++ b/app/src/bridge/lib/nativeMessaging.ts @@ -3,7 +3,6 @@ import { DecodeTransform, EncodeTransform } from "../../transforms"; import { Message } from "../messaging"; - export const decodeTransform = new DecodeTransform(); export const encodeTransform = new EncodeTransform(); diff --git a/app/src/bridge/lib/subtitles.ts b/app/src/bridge/lib/subtitles.ts index 9c8c45d..3f5aac4 100644 --- a/app/src/bridge/lib/subtitles.ts +++ b/app/src/bridge/lib/subtitles.ts @@ -2,13 +2,11 @@ import fs from "fs"; - /** * Reads a SubRip file and outputs text content as WebVTT. */ export async function convertSrtToVtt(srtFilePath: string) { - const fileStream = fs.createReadStream( - srtFilePath, { encoding: "utf-8" }); + const fileStream = fs.createReadStream(srtFilePath, { encoding: "utf-8" }); let fileContents = ""; for await (let chunk of fileStream) { @@ -21,7 +19,6 @@ export async function convertSrtToVtt(srtFilePath: string) { fileContents += chunk.replace(/$\r\n/gm, "\n"); } - let vttText = "WEBVTT\n"; /** @@ -30,7 +27,8 @@ export async function convertSrtToVtt(srtFilePath: string) { * (followed by a new line), then any text content until a blank * line. */ - const REGEX_CAPTION = /(?:(\d+)\n(\d{2}:\d{2}:\d{2},\d{3} --> \d{2}:\d{2}:\d{2},\d{3}))\n((?:.+)\n?)*/g; + const REGEX_CAPTION = + /(?:(\d+)\n(\d{2}:\d{2}:\d{2},\d{3} --> \d{2}:\d{2}:\d{2},\d{3}))\n((?:.+)\n?)*/g; /** * WebVTT is very similar to SubRip, the main differences being diff --git a/app/src/bridge/messaging.ts b/app/src/bridge/messaging.ts index 1195424..59556d5 100644 --- a/app/src/bridge/messaging.ts +++ b/app/src/bridge/messaging.ts @@ -1,121 +1,110 @@ "use strict"; -import { Image - , ReceiverStatus - , SenderApplication - , SenderMessage - , Volume } from "./components/cast/types"; - -import { ReceiverDevice - , ReceiverSelectionCast - , ReceiverSelectionStop } from "./types"; +import { + Image, + ReceiverStatus, + SenderApplication, + SenderMessage, + Volume +} from "./components/cast/types"; +import { + ReceiverDevice, + ReceiverSelectionCast, + ReceiverSelectionStop +} from "./types"; interface CastSessionUpdated { - sessionId: string - , statusText: string - , namespaces: Array<{ name: string }> - , volume: Volume + sessionId: string; + statusText: string; + namespaces: Array<{ name: string }>; + volume: Volume; } interface CastSessionCreated extends CastSessionUpdated { - appId: string - , appImages: Image[] - , displayName: string - , receiverFriendlyName: string - , senderApps: SenderApplication[] - , transportId: string + appId: string; + appImages: Image[]; + displayName: string; + receiverFriendlyName: string; + senderApps: SenderApplication[]; + transportId: string; } type MessageDefinitions = { - "shim:castSessionCreated": CastSessionCreated - , "shim:castSessionUpdated": CastSessionUpdated - , "shim:castSessionStopped": { - sessionId: string - } - - , "shim:receivedCastSessionMessage": { - sessionId: string - , namespace: string - , messageData: string - } - - , "shim:impl_sendCastMessage": { - sessionId: string - , messageId: string - , error?: string - } - - , "bridge:createCastSession": { - appId: string - , receiverDevice: ReceiverDevice - } - , "bridge:sendCastReceiverMessage": { - sessionId: string - , messageData: SenderMessage - , messageId: string - } - , "bridge:sendCastSessionMessage": { - sessionId: string - , namespace: string - , messageData: object | string - , messageId: string - } - - , "bridge:stopCastApp": { receiverDevice: ReceiverDevice } + "shim:castSessionCreated": CastSessionCreated; + "shim:castSessionUpdated": CastSessionUpdated; + "shim:castSessionStopped": { + sessionId: string; + }; + "shim:receivedCastSessionMessage": { + sessionId: string; + namespace: string; + messageData: string; + }; + "shim:impl_sendCastMessage": { + sessionId: string; + messageId: string; + error?: string; + }; + "bridge:createCastSession": { + appId: string; + receiverDevice: ReceiverDevice; + }; + "bridge:sendCastReceiverMessage": { + sessionId: string; + messageData: SenderMessage; + messageId: string; + }; + "bridge:sendCastSessionMessage": { + sessionId: string; + namespace: string; + messageData: object | string; + messageId: string; + }; + "bridge:stopCastApp": { receiverDevice: ReceiverDevice }; // Bridge messages - , "main:receiverSelector/selected": ReceiverSelectionCast - , "main:receiverSelector/stopped": ReceiverSelectionStop - , "main:receiverSelector/cancelled": {} - , "main:receiverSelector/error": string + "main:receiverSelector/selected": ReceiverSelectionCast; + "main:receiverSelector/stopped": ReceiverSelectionStop; + "main:receiverSelector/cancelled": {}; + "main:receiverSelector/error": string; /** * getInfo uses the old :/ form for compat with old bridge * versions. */ - , "bridge:getInfo": string - , "bridge:/getInfo": string - - , "bridge:startDiscovery": { - shouldWatchStatus: boolean - } - - , "bridge:openReceiverSelector": string - , "bridge:closeReceiverSelector": {} - - , "bridge:startMediaServer": { - filePath: string - , port: number - } - , "bridge:stopMediaServer": {} - - , "mediaCast:mediaServerStarted": { - mediaPath: string - , subtitlePaths: string[] - , localAddress: string - } - , "mediaCast:mediaServerStopped": {} - , "mediaCast:mediaServerError": {} - - - , "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 - } -} - + "bridge:getInfo": string; + "bridge:/getInfo": string; + "bridge:startDiscovery": { + shouldWatchStatus: boolean; + }; + "bridge:openReceiverSelector": string; + "bridge:closeReceiverSelector": {}; + "bridge:startMediaServer": { + filePath: string; + port: number; + }; + "bridge:stopMediaServer": {}; + "mediaCast:mediaServerStarted": { + mediaPath: string; + subtitlePaths: string[]; + localAddress: string; + }; + "mediaCast:mediaServerStopped": {}; + "mediaCast:mediaServerError": {}; + "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; + }; +}; interface MessageBase { subject: K; @@ -124,7 +113,7 @@ interface MessageBase { type Messages = { [K in keyof MessageDefinitions]: MessageBase; -} +}; /** * For better call semantics, make message data key optional if @@ -137,5 +126,4 @@ type NarrowedMessage> = : L : never; - export type Message = NarrowedMessage; diff --git a/app/src/bridge/types.ts b/app/src/bridge/types.ts index 40cdcde..bf1a816 100644 --- a/app/src/bridge/types.ts +++ b/app/src/bridge/types.ts @@ -2,17 +2,16 @@ import { ReceiverStatus } from "./components/cast/types"; - export enum ReceiverSelectorMediaType { - App = 1 - , Tab = 2 - , Screen = 4 - , File = 8 + App = 1, + Tab = 2, + Screen = 4, + File = 8 } export enum ReceiverSelectionActionType { - Cast = 1 - , Stop = 2 + Cast = 1, + Stop = 2 } export interface ReceiverSelectionCast { diff --git a/app/src/daemon.ts b/app/src/daemon.ts index 4f060de..796e3c2 100644 --- a/app/src/daemon.ts +++ b/app/src/daemon.ts @@ -6,9 +6,7 @@ import { Readable } from "stream"; import minimist from "minimist"; import WebSocket from "ws"; -import { DecodeTransform - , EncodeTransform } from "./transforms"; - +import { DecodeTransform, EncodeTransform } from "./transforms"; export function init(port: number) { process.stdout.write("Starting WebSocket server... "); @@ -18,13 +16,12 @@ export function init(port: number) { console.log("Done!"); }); - wss.on("error", (err) => { + wss.on("error", err => { // eslint-disable-next-line no-console console.log("Failed!"); console.error(err); }); - wss.on("connection", socket => { // Stream for incoming WebSocket messages const messageStream = new Readable({ objectMode: true }); @@ -35,27 +32,22 @@ export function init(port: number) { messageStream.push(JSON.parse(message)); }); - /** * Daemon and bridge are the same binary, so spawn a new * version of self in bridge mode. */ - const bridge = spawn(process.execPath, [ process.argv[1] ]); + const bridge = spawn(process.execPath, [process.argv[1]]); // socket -> bridge.stdin - messageStream - .pipe(new EncodeTransform()) - .pipe(bridge.stdin); + messageStream.pipe(new EncodeTransform()).pipe(bridge.stdin); // bridge.stdout -> socket - bridge.stdout - .pipe(new DecodeTransform()) - .on("data", data => { - // Socket can be CLOSING here - if (socket.readyState === WebSocket.OPEN) { - socket.send(JSON.stringify(data)); - } - }); + bridge.stdout.pipe(new DecodeTransform()).on("data", data => { + // Socket can be CLOSING here + if (socket.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify(data)); + } + }); // Handle termination socket.on("close", () => bridge.kill()); diff --git a/app/src/global.d.ts b/app/src/global.d.ts index a25669e..f09df52 100644 --- a/app/src/global.d.ts +++ b/app/src/global.d.ts @@ -1,6 +1,5 @@ declare type Nullable = T | null; -declare type DistributiveOmit = - T extends any - ? Omit - : never; +declare type DistributiveOmit = T extends any + ? Omit + : never; diff --git a/app/src/main.ts b/app/src/main.ts index 5593dd9..e8368e5 100644 --- a/app/src/main.ts +++ b/app/src/main.ts @@ -5,29 +5,28 @@ import minimist from "minimist"; import { __applicationVersion } from "../package.json"; const argv = minimist(process.argv.slice(2), { - boolean: [ "daemon", "help", "version" ] - , string: [ "__name", "port" ] - , alias: { - d: "daemon" - , h: "help" - , v: "version" - , p: "port" - } - , default: { - __name: path.basename(process.argv[0]) - , daemon: false - , port: "9556" + boolean: ["daemon", "help", "version"], + string: ["__name", "port"], + alias: { + d: "daemon", + h: "help", + v: "version", + p: "port" + }, + default: { + __name: path.basename(process.argv[0]), + daemon: false, + port: "9556" } }); - if (argv.version) { // eslint-disable-next-line no-console console.log(`v${__applicationVersion}`); } else if (argv.help) { // eslint-disable-next-line no-console console.log( -`Usage: ${argv.__name} [options] + `Usage: ${argv.__name} [options] Options: -h, --help Print usage info @@ -37,8 +36,8 @@ Options: options. -p, --port Set port number for WebSocket server. This must match the port set in the extension options. -`); - +` + ); } else if (argv.daemon) { const port = parseInt(argv.port); if (!port || port < 1025 || port > 65535) { @@ -46,10 +45,9 @@ Options: process.exit(1); } - import("./daemon") - .then(daemon => { - daemon.init(port); - }); + import("./daemon").then(daemon => { + daemon.init(port); + }); } else { import("./bridge"); } diff --git a/app/src/transforms.ts b/app/src/transforms.ts index b72ed7f..6e3e1c8 100755 --- a/app/src/transforms.ts +++ b/app/src/transforms.ts @@ -3,7 +3,6 @@ import { Transform } from "stream"; import { Message } from "./bridge/messaging"; - type ResponseHandlerFunction = (message: Message) => Promise; /** @@ -13,29 +12,27 @@ type ResponseHandlerFunction = (message: Message) => Promise; export class ResponseTransform extends Transform { constructor(private _handler: ResponseHandlerFunction) { super({ - readableObjectMode: true - , writableObjectMode: true + readableObjectMode: true, + writableObjectMode: true }); } public _transform( - chunk: Message - , _encoding: string - // tslint:disable-next-line:ban-types - , callback: Function) { - - Promise.resolve(this._handler(chunk)) - .then(res => { - if (res) { - callback(null, res); - } else { - callback(null); - } - }); + chunk: Message, + _encoding: string, + // tslint:disable-next-line:ban-types + callback: Function + ) { + Promise.resolve(this._handler(chunk)).then(res => { + if (res) { + callback(null, res); + } else { + callback(null); + } + }); } } - /** * Takes input, decodes the message string, parses as JSON * and outputs the parsed result. @@ -52,53 +49,52 @@ export class DecodeTransform extends Transform { } public _transform( - chunk: any - , _encoding: string - // tslint:disable-next-line:ban-types - , callback: Function) { + chunk: any, + _encoding: string, + // tslint:disable-next-line:ban-types + callback: Function + ) { + // Append next chunk to buffer + this._messageBuffer = Buffer.concat([this._messageBuffer, chunk]); - // Append next chunk to buffer - this._messageBuffer = Buffer.concat([ - this._messageBuffer - , chunk - ]); + for (;;) { + if (this._messageLength === undefined) { + if (this._messageBuffer.length >= 4) { + // Read message length and offset buffer + this._messageLength = this._messageBuffer.readUInt32LE(0); + this._messageBuffer = this._messageBuffer.slice(4); - for (;;) { - if (this._messageLength === undefined) { - if (this._messageBuffer.length >= 4) { - // Read message length and offset buffer - this._messageLength = this._messageBuffer.readUInt32LE(0); - this._messageBuffer = this._messageBuffer.slice(4); + // Next message chunk + continue; + } + } else { + if (this._messageBuffer.length >= this._messageLength) { + const message = JSON.parse( + this._messageBuffer + .slice(0, this._messageLength) + .toString() + ); - // Next message chunk - continue; - } - } else { - if (this._messageBuffer.length >= this._messageLength) { - const message = JSON.parse(this._messageBuffer - .slice(0, this._messageLength) - .toString()); + // Push message content + this.push(message); - // Push message content - this.push(message); + // Offset buffer to start of next message + this._messageBuffer = this._messageBuffer.slice( + this._messageLength + ); + this._messageLength = undefined; - // Offset buffer to start of next message - this._messageBuffer = this._messageBuffer.slice( - this._messageLength); - this._messageLength = undefined; + // Next message + continue; + } + } - // Next message - continue; - } - } - - // No complete messages left - callback(); - break; - } + // No complete messages left + callback(); + break; + } } - } - +} /** * Takes input, encodes the message length and content and @@ -112,11 +108,11 @@ export class EncodeTransform extends Transform { } public _transform( - chunk: any - , _encoding: string - // tslint:disable-next-line:ban-types - , callback: Function) { - + chunk: any, + _encoding: string, + // tslint:disable-next-line:ban-types + callback: Function + ) { const messageLength = Buffer.alloc(4); const message = Buffer.from(JSON.stringify(chunk)); @@ -124,9 +120,6 @@ export class EncodeTransform extends Transform { messageLength.writeUInt32LE(message.length, 0); // Output joined length and content - callback(null, Buffer.concat([ - messageLength - , message - ])); + callback(null, Buffer.concat([messageLength, message])); } - } +} diff --git a/ext/src/background/ShimManager.ts b/ext/src/background/ShimManager.ts index c34c768..c006c65 100644 --- a/ext/src/background/ShimManager.ts +++ b/ext/src/background/ShimManager.ts @@ -6,15 +6,15 @@ import logger from "../lib/logger"; import messaging, { Message, Port } from "../messaging"; import options from "../lib/options"; -import { ReceiverSelectionActionType - , ReceiverSelectorMediaType } from "./receiverSelector"; +import { + ReceiverSelectionActionType, + ReceiverSelectorMediaType +} from "./receiverSelector"; -import ReceiverSelectorManager - from "./receiverSelector/ReceiverSelectorManager"; +import ReceiverSelectorManager from "./receiverSelector/ReceiverSelectorManager"; import receiverDevices from "./receiverDevices"; - type AnyPort = Port | MessagePort; export interface Shim { @@ -25,8 +25,7 @@ export interface Shim { appId?: string; } - -export default new class ShimManager { +export default new (class ShimManager { private activeShims = new Set(); public async init() { @@ -40,8 +39,8 @@ export default new class ShimManager { receiverDevices.addEventListener("receiverDeviceUp", ev => { for (const shim of this.activeShims) { shim.contentPort.postMessage({ - subject: "shim:serviceUp" - , data: { receiverDevice: ev.detail.receiverDevice } + subject: "shim:serviceUp", + data: { receiverDevice: ev.detail.receiverDevice } }); } }); @@ -49,8 +48,8 @@ export default new class ShimManager { receiverDevices.addEventListener("receiverDeviceDown", ev => { for (const shim of this.activeShims) { shim.contentPort.postMessage({ - subject: "shim:serviceDown" - , data: { receiverDeviceId: ev.detail.receiverDeviceId } + subject: "shim:serviceDown", + data: { receiverDeviceId: ev.detail.receiverDeviceId } }); } }); @@ -74,19 +73,19 @@ export default new class ShimManager { : this.createShimFromContent(port)); shim.contentPort.postMessage({ - subject: "shim:initialized" - , data: await bridge.getInfo() + subject: "shim:initialized", + data: await bridge.getInfo() }); this.activeShims.add(shim); } private async createShimFromBackground( - contentPort: MessagePort): Promise { - + contentPort: MessagePort + ): Promise { const shim: Shim = { - bridgePort: await bridge.connect() - , contentPort + bridgePort: await bridge.connect(), + contentPort }; shim.bridgePort.onDisconnect.addListener(() => { @@ -105,12 +104,14 @@ export default new class ShimManager { return shim; } - private async createShimFromContent( - contentPort: Port): Promise { - - if (contentPort.sender?.tab?.id === undefined - || contentPort.sender?.frameId === undefined) { - throw logger.error("Content shim created with an invalid port context."); + private async createShimFromContent(contentPort: Port): Promise { + if ( + contentPort.sender?.tab?.id === undefined || + contentPort.sender?.frameId === undefined + ) { + throw logger.error( + "Content shim created with an invalid port context." + ); } /** @@ -118,20 +119,21 @@ export default new class ShimManager { * tab/frame ID, disconnect it. */ for (const activeShim of this.activeShims) { - if (activeShim.contentTabId === contentPort.sender.tab.id - && activeShim.contentFrameId === contentPort.sender.frameId) { + if ( + activeShim.contentTabId === contentPort.sender.tab.id && + activeShim.contentFrameId === contentPort.sender.frameId + ) { activeShim.bridgePort.disconnect(); } } const shim: Shim = { - bridgePort: await bridge.connect() - , contentPort - , contentTabId: contentPort.sender.tab.id - , contentFrameId: contentPort.sender.frameId + bridgePort: await bridge.connect(), + contentPort, + contentTabId: contentPort.sender.tab.id, + contentFrameId: contentPort.sender.frameId }; - const onContentPortMessage = (message: Message) => { this.handleContentMessage(shim, message); }; @@ -150,7 +152,6 @@ export default new class ShimManager { this.activeShims.delete(shim); }; - shim.bridgePort.onDisconnect.addListener(onDisconnect); shim.bridgePort.onMessage.addListener(onBridgePortMessage); @@ -161,7 +162,7 @@ export default new class ShimManager { } private async handleContentMessage(shim: Shim, message: Message) { - const [ destination ] = message.subject.split(":"); + const [destination] = message.subject.split(":"); if (destination === "bridge") { shim.bridgePort.postMessage(message); } @@ -172,8 +173,8 @@ export default new class ShimManager { for (const receiverDevice of receiverDevices.getDevices()) { shim.contentPort.postMessage({ - subject: "shim:serviceUp" - , data: { receiverDevice } + subject: "shim:serviceUp", + data: { receiverDevice } }); } @@ -181,15 +182,21 @@ export default new class ShimManager { } case "main:selectReceiver": { - if (shim.contentTabId === undefined - || shim.contentFrameId === undefined) { - throw logger.error("Shim associated with content sender missing tab/frame ID"); + if ( + shim.contentTabId === undefined || + shim.contentFrameId === undefined + ) { + throw logger.error( + "Shim associated with content sender missing tab/frame ID" + ); } try { const selection = - await ReceiverSelectorManager.getSelection( - shim.contentTabId, shim.contentFrameId); + await ReceiverSelectorManager.getSelection( + shim.contentTabId, + shim.contentFrameId + ); // Handle cancellation if (!selection) { @@ -207,25 +214,26 @@ export default new class ShimManager { * been changed, we need to cancel the current * sender and switch it out for the right one. */ - if (selection.mediaType !== - ReceiverSelectorMediaType.App) { - + if ( + selection.mediaType !== + ReceiverSelectorMediaType.App + ) { shim.contentPort.postMessage({ subject: "shim:selectReceiver/cancelled" }); loadSender({ - tabId: shim.contentTabId - , frameId: shim.contentFrameId - , selection + tabId: shim.contentTabId, + frameId: shim.contentFrameId, + selection }); break; } shim.contentPort.postMessage({ - subject: "shim:selectReceiver/selected" - , data: selection + subject: "shim:selectReceiver/selected", + data: selection }); break; @@ -233,8 +241,8 @@ export default new class ShimManager { case ReceiverSelectionActionType.Stop: { shim.contentPort.postMessage({ - subject: "shim:selectReceiver/stopped" - , data: selection + subject: "shim:selectReceiver/stopped", + data: selection }); break; @@ -257,7 +265,8 @@ export default new class ShimManager { case "main:sessionCreated": { const selector = await ReceiverSelectorManager.getSelector(); const shouldClose = await options.get( - "receiverSelectorWaitForConnection"); + "receiverSelectorWaitForConnection" + ); if (selector.isOpen && shouldClose) { selector.close(); @@ -267,4 +276,4 @@ export default new class ShimManager { } } } -}; +})(); diff --git a/ext/src/background/background.ts b/ext/src/background/background.ts index 29f417f..e47cbc5 100755 --- a/ext/src/background/background.ts +++ b/ext/src/background/background.ts @@ -7,8 +7,7 @@ import messaging from "../messaging"; import options from "../lib/options"; import bridge, { BridgeInfo } from "../lib/bridge"; -import ReceiverSelectorManager - from "./receiverSelector/ReceiverSelectorManager"; +import ReceiverSelectorManager from "./receiverSelector/ReceiverSelectorManager"; import ShimManager from "./ShimManager"; @@ -17,10 +16,8 @@ import receiverDevices from "./receiverDevices"; import { initMenus } from "./menus"; import { initWhitelist } from "./whitelist"; - const _ = browser.i18n.getMessage; - /** * On install, set the default options before initializing the * extension. On update, handle any unset values and set to @@ -36,7 +33,7 @@ browser.runtime.onInstalled.addListener(async details => { init(); break; } - + case "update": { // Set new defaults await options.update(defaultOptions); @@ -45,7 +42,6 @@ browser.runtime.onInstalled.addListener(async details => { } }); - /** * Sets up media overlay content script and handles toggling * on options change. @@ -62,10 +58,10 @@ async function initMediaOverlay() { try { contentScript = await browser.contentScripts.register({ - allFrames: true - , js: [{ file: "senders/media/overlay/overlayContentLoader.js" }] - , matches: [ "" ] - , runAt: "document_start" + allFrames: true, + js: [{ file: "senders/media/overlay/overlayContentLoader.js" }], + matches: [""], + runAt: "document_start" }); } catch (err) { logger.error("Failed to register media overlay"); @@ -76,7 +72,6 @@ async function initMediaOverlay() { await contentScript?.unregister(); } - registerMediaOverlayContentScript(); // Update if toggled @@ -90,7 +85,6 @@ async function initMediaOverlay() { }); } - /** * Checks whether the bridge can be reached and is compatible * with the current version of the extension. If not, triggers @@ -113,10 +107,11 @@ async function notifyBridgeCompat() { logger.info("... bridge incompatible!"); const updateNotificationId = await browser.notifications.create({ - type: "basic" - , title: `${ - _("extensionName")} — ${_("optionsBridgeIssueStatusTitle")}` - , message: info.isVersionOlder + type: "basic", + title: `${_("extensionName")} — ${_( + "optionsBridgeIssueStatusTitle" + )}`, + message: info.isVersionOlder ? _("optionsBridgeOlderAction") : _("optionsBridgeNewerAction") }); @@ -127,14 +122,12 @@ async function notifyBridgeCompat() { } browser.tabs.create({ - url: `https://github.com/hensm/fx_cast/releases/tag/v${ - info.expectedVersion}` + url: `https://github.com/hensm/fx_cast/releases/tag/v${info.expectedVersion}` }); }); } } - let isInitialized = false; async function init() { @@ -163,14 +156,13 @@ async function init() { await initWhitelist(); await initMediaOverlay(); - /** * When the browser action is clicked, open a receiver * selector and load a sender for the response. The * mirroring sender is loaded into the current tab at the * top-level frame. */ - browser.browserAction.onClicked.addListener(async tab => { + browser.browserAction.onClicked.addListener(async tab => { if (tab.id === undefined) { throw logger.error("Tab ID not found in browser action handler."); } @@ -178,9 +170,9 @@ async function init() { const selection = await ReceiverSelectorManager.getSelection(tab.id); if (selection) { loadSender({ - tabId: tab.id - , frameId: 0 - , selection + tabId: tab.id, + frameId: 0, + selection }); } }); diff --git a/ext/src/background/menus.ts b/ext/src/background/menus.ts index d61b5cb..0169627 100644 --- a/ext/src/background/menus.ts +++ b/ext/src/background/menus.ts @@ -6,22 +6,21 @@ import options from "../lib/options"; import { stringify } from "../lib/utils"; -import { ReceiverSelectionActionType - , ReceiverSelectorMediaType } from "./receiverSelector"; +import { + ReceiverSelectionActionType, + ReceiverSelectorMediaType +} from "./receiverSelector"; -import ReceiverSelectorManager - from "./receiverSelector/ReceiverSelectorManager"; +import ReceiverSelectorManager from "./receiverSelector/ReceiverSelectorManager"; const _ = browser.i18n.getMessage; - const URL_PATTERN_HTTP = "http://*/*"; const URL_PATTERN_HTTPS = "https://*/*"; const URL_PATTERN_FILE = "file://*/*"; -const URL_PATTERNS_REMOTE = [ URL_PATTERN_HTTP, URL_PATTERN_HTTPS ]; -const URL_PATTERNS_ALL = [ ...URL_PATTERNS_REMOTE, URL_PATTERN_FILE ]; - +const URL_PATTERNS_REMOTE = [URL_PATTERN_HTTP, URL_PATTERN_HTTPS]; +const URL_PATTERNS_ALL = [...URL_PATTERNS_REMOTE, URL_PATTERN_FILE]; type MenuId = string | number; @@ -39,44 +38,44 @@ export async function initMenus() { // Global "Cast..." menu item menuIdCast = browser.menus.create({ - contexts: [ "browser_action", "page", "tools_menu" ] - , title: _("contextCast") + contexts: ["browser_action", "page", "tools_menu"], + title: _("contextCast") }); //