mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-11 18:19:58 +00:00
Show app name in receiver selector if known based on app ID
This commit is contained in:
@@ -387,7 +387,8 @@ function initialize (options: InitializeOptions) {
|
|||||||
const application = status.applications[0];
|
const application = status.applications[0];
|
||||||
|
|
||||||
receiverStatusMessage.data.status.application = {
|
receiverStatusMessage.data.status.application = {
|
||||||
displayName: application.displayName
|
appId: application.appId
|
||||||
|
, displayName: application.displayName
|
||||||
, isIdleScreen: application.isIdleScreen
|
, isIdleScreen: application.isIdleScreen
|
||||||
, statusText: application.statusText
|
, statusText: application.statusText
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export interface Shim {
|
|||||||
contentPort: Port;
|
contentPort: Port;
|
||||||
contentTabId?: number;
|
contentTabId?: number;
|
||||||
contentFrameId?: number;
|
contentFrameId?: number;
|
||||||
|
requestedAppId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -33,6 +34,18 @@ export default new class ShimManager {
|
|||||||
await this.initStatusListeners();
|
await this.initStatusListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getShim (tabId: number, frameId?: number) {
|
||||||
|
for (const activeShim of this.activeShims) {
|
||||||
|
if (activeShim.contentTabId === tabId) {
|
||||||
|
if (frameId && activeShim.contentFrameId !== frameId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeShim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async createShim (port: Port) {
|
public async createShim (port: Port) {
|
||||||
const shim = await (port instanceof MessagePort
|
const shim = await (port instanceof MessagePort
|
||||||
? this.createShimFromBackground(port)
|
? this.createShimFromBackground(port)
|
||||||
@@ -129,6 +142,8 @@ export default new class ShimManager {
|
|||||||
|
|
||||||
switch (message.subject) {
|
switch (message.subject) {
|
||||||
case "main:/shimInitialized": {
|
case "main:/shimInitialized": {
|
||||||
|
shim.requestedAppId = message.data.appId;
|
||||||
|
|
||||||
for (const receiver of StatusManager.getReceivers()) {
|
for (const receiver of StatusManager.getReceivers()) {
|
||||||
shim.contentPort.postMessage({
|
shim.contentPort.postMessage({
|
||||||
subject: "shim:/serviceUp"
|
subject: "shim:/serviceUp"
|
||||||
@@ -148,7 +163,8 @@ export default new class ShimManager {
|
|||||||
const selection = await ReceiverSelectorManager
|
const selection = await ReceiverSelectorManager
|
||||||
.getSelection(
|
.getSelection(
|
||||||
ReceiverSelectorMediaType.App
|
ReceiverSelectorMediaType.App
|
||||||
, availableMediaTypes);
|
, availableMediaTypes
|
||||||
|
, shim.requestedAppId);
|
||||||
|
|
||||||
// Handle cancellation
|
// Handle cancellation
|
||||||
if (!selection) {
|
if (!selection) {
|
||||||
|
|||||||
@@ -65,10 +65,12 @@ function initBrowserAction () {
|
|||||||
* top-level frame.
|
* top-level frame.
|
||||||
*/
|
*/
|
||||||
browser.browserAction.onClicked.addListener(async tab => {
|
browser.browserAction.onClicked.addListener(async tab => {
|
||||||
|
const currentShim = ShimManager.getShim(tab.id);
|
||||||
const selection = await ReceiverSelectorManager.getSelection(
|
const selection = await ReceiverSelectorManager.getSelection(
|
||||||
ReceiverSelectorMediaType.Tab
|
ReceiverSelectorMediaType.Tab
|
||||||
, getMediaTypesForPageUrl(tab.url)
|
, getMediaTypesForPageUrl(tab.url)
|
||||||
& ~ReceiverSelectorMediaType.App);
|
& ~ReceiverSelectorMediaType.App
|
||||||
|
, currentShim.requestedAppId);
|
||||||
|
|
||||||
if (selection) {
|
if (selection) {
|
||||||
loadSender({
|
loadSender({
|
||||||
@@ -159,9 +161,11 @@ async function initMenus () {
|
|||||||
|
|
||||||
switch (info.menuItemId) {
|
switch (info.menuItemId) {
|
||||||
case menuIdMediaCast: {
|
case menuIdMediaCast: {
|
||||||
|
const currentShim = ShimManager.getShim(tab.id, info.frameId);
|
||||||
const selection = await ReceiverSelectorManager.getSelection(
|
const selection = await ReceiverSelectorManager.getSelection(
|
||||||
ReceiverSelectorMediaType.App
|
ReceiverSelectorMediaType.App
|
||||||
, availableMediaTypes);
|
, availableMediaTypes
|
||||||
|
, currentShim.requestedAppId);
|
||||||
|
|
||||||
// Selection cancelled
|
// Selection cancelled
|
||||||
if (!selection) {
|
if (!selection) {
|
||||||
@@ -200,9 +204,11 @@ async function initMenus () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case menuIdMirroringCast: {
|
case menuIdMirroringCast: {
|
||||||
|
const currentShim = ShimManager.getShim(tab.id, info.frameId);
|
||||||
const selection = await ReceiverSelectorManager.getSelection(
|
const selection = await ReceiverSelectorManager.getSelection(
|
||||||
ReceiverSelectorMediaType.Tab
|
ReceiverSelectorMediaType.Tab
|
||||||
, availableMediaTypes & ~ReceiverSelectorMediaType.App);
|
, availableMediaTypes & ~ReceiverSelectorMediaType.App
|
||||||
|
, currentShim.requestedAppId);
|
||||||
|
|
||||||
loadSender({
|
loadSender({
|
||||||
tabId: tab.id
|
tabId: tab.id
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import bridge from "../../lib/bridge";
|
import bridge from "../../lib/bridge";
|
||||||
|
import knownApps from "../../lib/knownApps";
|
||||||
import options from "../../lib/options";
|
import options from "../../lib/options";
|
||||||
|
|
||||||
import { TypedEventTarget } from "../../lib/typedEvents";
|
import { TypedEventTarget } from "../../lib/typedEvents";
|
||||||
@@ -43,7 +44,8 @@ export default class NativeReceiverSelector
|
|||||||
public async open (
|
public async open (
|
||||||
receivers: Receiver[]
|
receivers: Receiver[]
|
||||||
, defaultMediaType: ReceiverSelectorMediaType
|
, defaultMediaType: ReceiverSelectorMediaType
|
||||||
, availableMediaTypes: ReceiverSelectorMediaType): Promise<void> {
|
, availableMediaTypes: ReceiverSelectorMediaType
|
||||||
|
, requestedAppId: string): Promise<void> {
|
||||||
|
|
||||||
this.bridgePort = await bridge.connect();
|
this.bridgePort = await bridge.connect();
|
||||||
|
|
||||||
@@ -94,7 +96,8 @@ export default class NativeReceiverSelector
|
|||||||
|
|
||||||
, i18n_extensionName: _("extensionName")
|
, i18n_extensionName: _("extensionName")
|
||||||
, i18n_castButtonTitle: _("popupCastButtonTitle")
|
, i18n_castButtonTitle: _("popupCastButtonTitle")
|
||||||
, i18n_mediaTypeApp: _("popupMediaTypeApp")
|
, i18n_mediaTypeApp:
|
||||||
|
knownApps[requestedAppId] ?? _("popupMediaTypeApp")
|
||||||
, i18n_mediaTypeTab: _("popupMediaTypeTab")
|
, i18n_mediaTypeTab: _("popupMediaTypeTab")
|
||||||
, i18n_mediaTypeScreen: _("popupMediaTypeScreen")
|
, i18n_mediaTypeScreen: _("popupMediaTypeScreen")
|
||||||
, i18n_mediaTypeFile: _("popupMediaTypeFile")
|
, i18n_mediaTypeFile: _("popupMediaTypeFile")
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export default class PopupReceiverSelector
|
|||||||
private wasReceiverSelected: boolean = false;
|
private wasReceiverSelected: boolean = false;
|
||||||
|
|
||||||
private _isOpen: boolean = false;
|
private _isOpen: boolean = false;
|
||||||
|
private requestedAppId: string;
|
||||||
|
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
@@ -59,6 +60,11 @@ export default class PopupReceiverSelector
|
|||||||
this.messagePortDisconnected = true;
|
this.messagePortDisconnected = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.messagePort.postMessage({
|
||||||
|
subject: "popup:/sendRequestedAppId"
|
||||||
|
, data: { requestedAppId: this.requestedAppId }
|
||||||
|
});
|
||||||
|
|
||||||
this.messagePort.postMessage({
|
this.messagePort.postMessage({
|
||||||
subject: "popup:/populateReceiverList"
|
subject: "popup:/populateReceiverList"
|
||||||
, data: {
|
, data: {
|
||||||
@@ -77,7 +83,10 @@ export default class PopupReceiverSelector
|
|||||||
public async open (
|
public async open (
|
||||||
receivers: Receiver[]
|
receivers: Receiver[]
|
||||||
, defaultMediaType: ReceiverSelectorMediaType
|
, defaultMediaType: ReceiverSelectorMediaType
|
||||||
, availableMediaTypes: ReceiverSelectorMediaType): Promise<void> {
|
, availableMediaTypes: ReceiverSelectorMediaType
|
||||||
|
, requestedAppId: string): Promise<void> {
|
||||||
|
|
||||||
|
this.requestedAppId = requestedAppId;
|
||||||
|
|
||||||
// If popup already exists, close it
|
// If popup already exists, close it
|
||||||
if (this.windowId) {
|
if (this.windowId) {
|
||||||
@@ -124,6 +133,7 @@ export default class PopupReceiverSelector
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._isOpen = false;
|
this._isOpen = false;
|
||||||
|
this.requestedAppId = null;
|
||||||
|
|
||||||
if (this.messagePort && !this.messagePortDisconnected) {
|
if (this.messagePort && !this.messagePortDisconnected) {
|
||||||
this.messagePort.disconnect();
|
this.messagePort.disconnect();
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ export default interface ReceiverSelector
|
|||||||
|
|
||||||
open (receivers: Receiver[]
|
open (receivers: Receiver[]
|
||||||
, defaultMediaType: ReceiverSelectorMediaType
|
, defaultMediaType: ReceiverSelectorMediaType
|
||||||
, availableMediaTypes: ReceiverSelectorMediaType): void;
|
, availableMediaTypes: ReceiverSelectorMediaType
|
||||||
|
, requestedAppId: string): void;
|
||||||
|
|
||||||
close (): void;
|
close (): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ async function getSelection (
|
|||||||
, availableMediaTypes =
|
, availableMediaTypes =
|
||||||
ReceiverSelectorMediaType.Tab
|
ReceiverSelectorMediaType.Tab
|
||||||
| ReceiverSelectorMediaType.Screen
|
| ReceiverSelectorMediaType.Screen
|
||||||
| ReceiverSelectorMediaType.File)
|
| ReceiverSelectorMediaType.File
|
||||||
|
, requestedAppId: string)
|
||||||
: Promise<ReceiverSelection> {
|
: Promise<ReceiverSelection> {
|
||||||
|
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
@@ -104,7 +105,8 @@ async function getSelection (
|
|||||||
sharedSelector.open(
|
sharedSelector.open(
|
||||||
Array.from(StatusManager.getReceivers())
|
Array.from(StatusManager.getReceivers())
|
||||||
, defaultMediaType
|
, defaultMediaType
|
||||||
, availableMediaTypes);
|
, availableMediaTypes
|
||||||
|
, requestedAppId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
ext/src/lib/knownApps.ts
Normal file
23
ext/src/lib/knownApps.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Just keep a list of IDs and cache names from the Google API:
|
||||||
|
* https://clients3.google.com/cast/chromecast/device/app?a=[appId]
|
||||||
|
*
|
||||||
|
* Also, localization since the API supports it.
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
"CA5E8412": "Netflix"
|
||||||
|
, "233637DE": "YouTube"
|
||||||
|
, "17608BC8": "Prime Video"
|
||||||
|
, "CC32E753": "Spotify"
|
||||||
|
, "5E81F6DB": "BBC iPlayer"
|
||||||
|
, "03977A48": "BBC Sounds"
|
||||||
|
, "AA666EDD": "Crunchyroll"
|
||||||
|
, "10AAD887": "All 4"
|
||||||
|
, "9AC194DC": "Plex"
|
||||||
|
, "CD7B9F59": "Global Player Live"
|
||||||
|
, "B3DCF968": "Twitch"
|
||||||
|
, "B88B034A": "Dailymotion"
|
||||||
|
, "CC1AD845": "TEST"
|
||||||
|
} as Record<string, string>;
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
"all_frames": true
|
"all_frames": true
|
||||||
, "js": [
|
, "js": [
|
||||||
"shim/content.js"
|
"shim/content.js"
|
||||||
, "senders/media/overlay/overlayContentLoader.js"
|
//, "senders/media/overlay/overlayContentLoader.js"
|
||||||
]
|
]
|
||||||
, "matches": [ "<all_urls>" ]
|
, "matches": [ "<all_urls>" ]
|
||||||
, "run_at": "document_start"
|
, "run_at": "document_start"
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ export function initialize (
|
|||||||
|
|
||||||
sendMessageResponse({
|
sendMessageResponse({
|
||||||
subject: "main:/shimInitialized"
|
subject: "main:/shimInitialized"
|
||||||
|
, data: { appId: apiConfig.sessionRequest.appId }
|
||||||
});
|
});
|
||||||
|
|
||||||
apiConfig.receiverListener(receiverList.length
|
apiConfig.receiverListener(receiverList.length
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
|
|
||||||
|
import knownApps from "../../lib/knownApps";
|
||||||
|
|
||||||
import { getNextEllipsis } from "../../lib/utils";
|
import { getNextEllipsis } from "../../lib/utils";
|
||||||
import { Message, Receiver } from "../../types";
|
import { Message, Receiver } from "../../types";
|
||||||
|
|
||||||
@@ -30,6 +32,7 @@ interface PopupAppState {
|
|||||||
availableMediaTypes: ReceiverSelectorMediaType;
|
availableMediaTypes: ReceiverSelectorMediaType;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
filePath: string;
|
filePath: string;
|
||||||
|
requestedAppId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PopupApp extends Component<{}, PopupAppState> {
|
class PopupApp extends Component<{}, PopupAppState> {
|
||||||
@@ -46,6 +49,7 @@ class PopupApp extends Component<{}, PopupAppState> {
|
|||||||
, availableMediaTypes: ReceiverSelectorMediaType.App
|
, availableMediaTypes: ReceiverSelectorMediaType.App
|
||||||
, isLoading: false
|
, isLoading: false
|
||||||
, filePath: null
|
, filePath: null
|
||||||
|
, requestedAppId: null
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store window ref
|
// Store window ref
|
||||||
@@ -64,6 +68,14 @@ class PopupApp extends Component<{}, PopupAppState> {
|
|||||||
|
|
||||||
this.port.onMessage.addListener((message: Message) => {
|
this.port.onMessage.addListener((message: Message) => {
|
||||||
switch (message.subject) {
|
switch (message.subject) {
|
||||||
|
case "popup:/sendRequestedAppId": {
|
||||||
|
this.setState({
|
||||||
|
requestedAppId: message.data.requestedAppId
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case "popup:/populateReceiverList": {
|
case "popup:/populateReceiverList": {
|
||||||
this.defaultMediaType = message.data.defaultMediaType;
|
this.defaultMediaType = message.data.defaultMediaType;
|
||||||
|
|
||||||
@@ -124,7 +136,8 @@ class PopupApp extends Component<{}, PopupAppState> {
|
|||||||
<option value={ ReceiverSelectorMediaType.App }
|
<option value={ ReceiverSelectorMediaType.App }
|
||||||
disabled={ !(this.state.availableMediaTypes
|
disabled={ !(this.state.availableMediaTypes
|
||||||
& ReceiverSelectorMediaType.App) }>
|
& ReceiverSelectorMediaType.App) }>
|
||||||
{ _("popupMediaTypeApp") }
|
{ knownApps[this.state.requestedAppId]
|
||||||
|
?? _("popupMediaTypeApp") }
|
||||||
</option>
|
</option>
|
||||||
<option value={ ReceiverSelectorMediaType.Tab }
|
<option value={ ReceiverSelectorMediaType.Tab }
|
||||||
disabled={ !(this.state.availableMediaTypes
|
disabled={ !(this.state.availableMediaTypes
|
||||||
|
|||||||
Reference in New Issue
Block a user