mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-13 02:49:58 +00:00
Add auto-expansion of media controls for devices with connected sessions
This commit is contained in:
@@ -388,6 +388,10 @@
|
|||||||
"message": "Close after losing focus",
|
"message": "Close after losing focus",
|
||||||
"description": "Receiver selector close if focus lost option checkbox label."
|
"description": "Receiver selector close if focus lost option checkbox label."
|
||||||
},
|
},
|
||||||
|
"optionsReceiverSelectorExpandActive": {
|
||||||
|
"message": "Expand media controls for connected devices",
|
||||||
|
"description": "Receiver selector expand active checkbox label."
|
||||||
|
},
|
||||||
|
|
||||||
"optionsSiteWhitelistCategoryName": {
|
"optionsSiteWhitelistCategoryName": {
|
||||||
"message": "Site whitelist",
|
"message": "Site whitelist",
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import type {
|
|||||||
const POPUP_URL = browser.runtime.getURL("ui/popup/index.html");
|
const POPUP_URL = browser.runtime.getURL("ui/popup/index.html");
|
||||||
|
|
||||||
export interface ReceiverSelection {
|
export interface ReceiverSelection {
|
||||||
receiverDevice: ReceiverDevice;
|
device: ReceiverDevice;
|
||||||
mediaType: ReceiverSelectorMediaType;
|
mediaType: ReceiverSelectorMediaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
private messagePort?: Port;
|
private messagePort?: Port;
|
||||||
private messagePortDisconnected?: boolean;
|
private messagePortDisconnected?: boolean;
|
||||||
|
|
||||||
private receiverDevices?: ReceiverDevice[];
|
private devices?: ReceiverDevice[];
|
||||||
|
|
||||||
private defaultMediaType?: ReceiverSelectorMediaType;
|
private defaultMediaType?: ReceiverSelectorMediaType;
|
||||||
private availableMediaTypes?: ReceiverSelectorMediaType;
|
private availableMediaTypes?: ReceiverSelectorMediaType;
|
||||||
@@ -86,7 +86,7 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
* Creates and opens a receiver selector window.
|
* Creates and opens a receiver selector window.
|
||||||
*/
|
*/
|
||||||
public async open(opts: {
|
public async open(opts: {
|
||||||
receiverDevices: ReceiverDevice[];
|
devices: ReceiverDevice[];
|
||||||
defaultMediaType: ReceiverSelectorMediaType;
|
defaultMediaType: ReceiverSelectorMediaType;
|
||||||
availableMediaTypes: ReceiverSelectorMediaType;
|
availableMediaTypes: ReceiverSelectorMediaType;
|
||||||
appInfo?: ReceiverSelectorAppInfo;
|
appInfo?: ReceiverSelectorAppInfo;
|
||||||
@@ -100,7 +100,7 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
await browser.windows.remove(this.windowId);
|
await browser.windows.remove(this.windowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.receiverDevices = opts.receiverDevices;
|
this.devices = opts.devices;
|
||||||
this.defaultMediaType = opts.defaultMediaType;
|
this.defaultMediaType = opts.defaultMediaType;
|
||||||
this.availableMediaTypes = opts.availableMediaTypes;
|
this.availableMediaTypes = opts.availableMediaTypes;
|
||||||
|
|
||||||
@@ -149,13 +149,11 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Updates receiver devices displayed in the receiver selector. */
|
/** Updates receiver devices displayed in the receiver selector. */
|
||||||
public update(receiverDevices: ReceiverDevice[]) {
|
public update(devices: ReceiverDevice[], connectedSessionIds: string[]) {
|
||||||
this.receiverDevices = receiverDevices;
|
this.devices = devices;
|
||||||
this.messagePort?.postMessage({
|
this.messagePort?.postMessage({
|
||||||
subject: "popup:update",
|
subject: "popup:update",
|
||||||
data: {
|
data: { devices, connectedSessionIds }
|
||||||
receiverDevices: this.receiverDevices
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +189,7 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.receiverDevices === undefined ||
|
this.devices === undefined ||
|
||||||
this.defaultMediaType === undefined ||
|
this.defaultMediaType === undefined ||
|
||||||
this.availableMediaTypes === undefined
|
this.availableMediaTypes === undefined
|
||||||
) {
|
) {
|
||||||
@@ -214,7 +212,7 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
this.messagePort.postMessage({
|
this.messagePort.postMessage({
|
||||||
subject: "popup:update",
|
subject: "popup:update",
|
||||||
data: {
|
data: {
|
||||||
receiverDevices: this.receiverDevices,
|
devices: this.devices,
|
||||||
defaultMediaType: this.defaultMediaType,
|
defaultMediaType: this.defaultMediaType,
|
||||||
availableMediaTypes: this.availableMediaTypes
|
availableMediaTypes: this.availableMediaTypes
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,10 +108,10 @@ function isSameContext(ctx1?: ContentContext, ctx2?: ContentContext) {
|
|||||||
let baseConfig: BaseConfig;
|
let baseConfig: BaseConfig;
|
||||||
let receiverSelector: Optional<ReceiverSelector>;
|
let receiverSelector: Optional<ReceiverSelector>;
|
||||||
|
|
||||||
|
const activeInstances = new Set<CastInstance>();
|
||||||
|
|
||||||
/** Keeps track of cast API instances and provides bridge messaging. */
|
/** Keeps track of cast API instances and provides bridge messaging. */
|
||||||
const castManager = new (class {
|
const castManager = new (class {
|
||||||
private activeInstances = new Set<CastInstance>();
|
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
// Handle incoming instance connections
|
// Handle incoming instance connections
|
||||||
messaging.onConnect.addListener(async port => {
|
messaging.onConnect.addListener(async port => {
|
||||||
@@ -127,7 +127,7 @@ const castManager = new (class {
|
|||||||
const updateReceiverAvailability = () => {
|
const updateReceiverAvailability = () => {
|
||||||
const isAvailable = deviceManager.getDevices().length > 0;
|
const isAvailable = deviceManager.getDevices().length > 0;
|
||||||
|
|
||||||
for (const instance of this.activeInstances) {
|
for (const instance of activeInstances) {
|
||||||
instance.contentPort.postMessage({
|
instance.contentPort.postMessage({
|
||||||
subject: "cast:receiverAvailabilityUpdated",
|
subject: "cast:receiverAvailabilityUpdated",
|
||||||
data: { isAvailable }
|
data: { isAvailable }
|
||||||
@@ -146,7 +146,7 @@ const castManager = new (class {
|
|||||||
* Finds a cast instance at the given tab (and optionally frame) ID.
|
* Finds a cast instance at the given tab (and optionally frame) ID.
|
||||||
*/
|
*/
|
||||||
getInstanceAt(tabId: number, frameId?: number) {
|
getInstanceAt(tabId: number, frameId?: number) {
|
||||||
for (const instance of this.activeInstances) {
|
for (const instance of activeInstances) {
|
||||||
if (instance.contentContext?.tabId === tabId) {
|
if (instance.contentContext?.tabId === tabId) {
|
||||||
// If frame ID doesn't match go to next instance
|
// If frame ID doesn't match go to next instance
|
||||||
if (frameId && instance.contentContext.frameId !== frameId) {
|
if (frameId && instance.contentContext.frameId !== frameId) {
|
||||||
@@ -159,7 +159,7 @@ const castManager = new (class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getInstanceByDeviceId(deviceId: string) {
|
getInstanceByDeviceId(deviceId: string) {
|
||||||
for (const instance of this.activeInstances) {
|
for (const instance of activeInstances) {
|
||||||
if (instance.session?.deviceId === deviceId) return instance;
|
if (instance.session?.deviceId === deviceId) return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ const castManager = new (class {
|
|||||||
? this.createInstanceFromBackground(port, contentContext)
|
? this.createInstanceFromBackground(port, contentContext)
|
||||||
: this.createInstanceFromContent(port, isTrusted));
|
: this.createInstanceFromContent(port, isTrusted));
|
||||||
|
|
||||||
this.activeInstances.add(instance);
|
activeInstances.add(instance);
|
||||||
|
|
||||||
instance.contentPort.postMessage({
|
instance.contentPort.postMessage({
|
||||||
subject: "cast:instanceCreated",
|
subject: "cast:instanceCreated",
|
||||||
@@ -201,10 +201,10 @@ const castManager = new (class {
|
|||||||
|
|
||||||
// Ensure only one instance per context
|
// Ensure only one instance per context
|
||||||
if (contentContext) {
|
if (contentContext) {
|
||||||
for (const instance of this.activeInstances) {
|
for (const instance of activeInstances) {
|
||||||
if (isSameContext(instance.contentContext, contentContext)) {
|
if (isSameContext(instance.contentContext, contentContext)) {
|
||||||
instance.bridgePort.disconnect();
|
instance.bridgePort.disconnect();
|
||||||
this.activeInstances.delete(instance);
|
activeInstances.delete(instance);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,7 @@ const castManager = new (class {
|
|||||||
|
|
||||||
instance.bridgePort.onDisconnect.addListener(() => {
|
instance.bridgePort.onDisconnect.addListener(() => {
|
||||||
contentPort.close();
|
contentPort.close();
|
||||||
this.activeInstances.delete(instance);
|
activeInstances.delete(instance);
|
||||||
});
|
});
|
||||||
|
|
||||||
// bridge -> cast instance
|
// bridge -> cast instance
|
||||||
@@ -246,7 +246,7 @@ const castManager = new (class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure only one instance per context
|
// Ensure only one instance per context
|
||||||
for (const instance of this.activeInstances) {
|
for (const instance of activeInstances) {
|
||||||
if (
|
if (
|
||||||
isSameContext(
|
isSameContext(
|
||||||
instance.contentContext,
|
instance.contentContext,
|
||||||
@@ -277,7 +277,7 @@ const castManager = new (class {
|
|||||||
instance.bridgePort.disconnect();
|
instance.bridgePort.disconnect();
|
||||||
contentPort.disconnect();
|
contentPort.disconnect();
|
||||||
|
|
||||||
this.activeInstances.delete(instance);
|
activeInstances.delete(instance);
|
||||||
};
|
};
|
||||||
|
|
||||||
instance.bridgePort.onDisconnect.addListener(onDisconnect);
|
instance.bridgePort.onDisconnect.addListener(onDisconnect);
|
||||||
@@ -433,7 +433,7 @@ const castManager = new (class {
|
|||||||
subject: "bridge:createCastSession",
|
subject: "bridge:createCastSession",
|
||||||
data: {
|
data: {
|
||||||
appId: sessionRequest.appId,
|
appId: sessionRequest.appId,
|
||||||
receiverDevice: selection.receiverDevice
|
receiverDevice: selection.device
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -498,7 +498,7 @@ const castManager = new (class {
|
|||||||
instance.contentPort.postMessage({
|
instance.contentPort.postMessage({
|
||||||
subject: "cast:receiverAction",
|
subject: "cast:receiverAction",
|
||||||
data: {
|
data: {
|
||||||
receiver: createReceiver(selection.receiverDevice),
|
receiver: createReceiver(selection.device),
|
||||||
action: ReceiverAction.CAST
|
action: ReceiverAction.CAST
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -507,7 +507,7 @@ const castManager = new (class {
|
|||||||
subject: "bridge:createCastSession",
|
subject: "bridge:createCastSession",
|
||||||
data: {
|
data: {
|
||||||
appId: instance.apiConfig?.sessionRequest.appId,
|
appId: instance.apiConfig?.sessionRequest.appId,
|
||||||
receiverDevice: selection.receiverDevice
|
receiverDevice: selection.device
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -519,7 +519,7 @@ const castManager = new (class {
|
|||||||
await browser.tabs.executeScript(contentContext.tabId, {
|
await browser.tabs.executeScript(contentContext.tabId, {
|
||||||
code: stringify`
|
code: stringify`
|
||||||
window.mirroringMediaType = ${selection.mediaType};
|
window.mirroringMediaType = ${selection.mediaType};
|
||||||
window.receiverDevice = ${selection.receiverDevice};
|
window.receiverDevice = ${selection.device};
|
||||||
window.contextTabId = ${contentContext.tabId};
|
window.contextTabId = ${contentContext.tabId};
|
||||||
`,
|
`,
|
||||||
frameId: contentContext.frameId
|
frameId: contentContext.frameId
|
||||||
@@ -695,7 +695,7 @@ async function getReceiverSelection(selectionOpts: {
|
|||||||
);
|
);
|
||||||
|
|
||||||
receiverSelector.open({
|
receiverSelector.open({
|
||||||
receiverDevices: deviceManager.getDevices(),
|
devices: deviceManager.getDevices(),
|
||||||
defaultMediaType,
|
defaultMediaType,
|
||||||
availableMediaTypes,
|
availableMediaTypes,
|
||||||
appInfo,
|
appInfo,
|
||||||
@@ -751,7 +751,16 @@ function createSelector() {
|
|||||||
selector.addEventListener("mediaMessage", onMediaMessage);
|
selector.addEventListener("mediaMessage", onMediaMessage);
|
||||||
|
|
||||||
// Update selector data whenever devices change/update
|
// Update selector data whenever devices change/update
|
||||||
const onDeviceChange = () => selector.update(deviceManager.getDevices());
|
const onDeviceChange = () => {
|
||||||
|
const connectedSessionIds: string[] = [];
|
||||||
|
for (const instance of activeInstances) {
|
||||||
|
if (instance.session) {
|
||||||
|
connectedSessionIds.push(instance.session.sessionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selector.update(deviceManager.getDevices(), connectedSessionIds);
|
||||||
|
};
|
||||||
|
|
||||||
deviceManager.addEventListener("deviceUp", onDeviceChange);
|
deviceManager.addEventListener("deviceUp", onDeviceChange);
|
||||||
deviceManager.addEventListener("deviceDown", onDeviceChange);
|
deviceManager.addEventListener("deviceDown", onDeviceChange);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export interface Options {
|
|||||||
mirroringAppId: string;
|
mirroringAppId: string;
|
||||||
receiverSelectorCloseIfFocusLost: boolean;
|
receiverSelectorCloseIfFocusLost: boolean;
|
||||||
receiverSelectorWaitForConnection: boolean;
|
receiverSelectorWaitForConnection: boolean;
|
||||||
|
receiverSelectorExpandActive: boolean;
|
||||||
siteWhitelistEnabled: boolean;
|
siteWhitelistEnabled: boolean;
|
||||||
siteWhitelist: WhitelistItemData[];
|
siteWhitelist: WhitelistItemData[];
|
||||||
siteWhitelistCustomUserAgent: string;
|
siteWhitelistCustomUserAgent: string;
|
||||||
@@ -40,6 +41,7 @@ export default {
|
|||||||
mirroringAppId: MIRRORING_APP_ID,
|
mirroringAppId: MIRRORING_APP_ID,
|
||||||
receiverSelectorCloseIfFocusLost: true,
|
receiverSelectorCloseIfFocusLost: true,
|
||||||
receiverSelectorWaitForConnection: true,
|
receiverSelectorWaitForConnection: true,
|
||||||
|
receiverSelectorExpandActive: true,
|
||||||
siteWhitelistEnabled: true,
|
siteWhitelistEnabled: true,
|
||||||
siteWhitelist: [{ pattern: "https://www.netflix.com/*", isEnabled: true }],
|
siteWhitelist: [{ pattern: "https://www.netflix.com/*", isEnabled: true }],
|
||||||
siteWhitelistCustomUserAgent: "",
|
siteWhitelistCustomUserAgent: "",
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ type ExtMessageDefinitions = {
|
|||||||
};
|
};
|
||||||
/** Updates selector popup with new data. */
|
/** Updates selector popup with new data. */
|
||||||
"popup:update": {
|
"popup:update": {
|
||||||
receiverDevices: ReceiverDevice[];
|
devices: ReceiverDevice[];
|
||||||
|
connectedSessionIds?: string[];
|
||||||
defaultMediaType?: ReceiverSelectorMediaType;
|
defaultMediaType?: ReceiverSelectorMediaType;
|
||||||
availableMediaTypes?: ReceiverSelectorMediaType;
|
availableMediaTypes?: ReceiverSelectorMediaType;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -259,6 +259,22 @@
|
|||||||
{_("optionsReceiverSelectorCloseIfFocusLost")}
|
{_("optionsReceiverSelectorCloseIfFocusLost")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="option option--inline">
|
||||||
|
<div class="option__control">
|
||||||
|
<input
|
||||||
|
id="receiverSelectorExpandActive"
|
||||||
|
type="checkbox"
|
||||||
|
bind:checked={opts.receiverSelectorExpandActive}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<label
|
||||||
|
class="option__label"
|
||||||
|
for="receiverSelectorExpandActive"
|
||||||
|
>
|
||||||
|
{_("optionsReceiverSelectorExpandActive")}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
/** Devices to display. */
|
/** Devices to display. */
|
||||||
let devices: ReceiverDevice[] = [];
|
let devices: ReceiverDevice[] = [];
|
||||||
|
/** IDs of sessions connected by this extension. */
|
||||||
|
let connectedSessionIds: string[] = [];
|
||||||
|
|
||||||
/** Sender app info (if available). */
|
/** Sender app info (if available). */
|
||||||
let appInfo: Optional<ReceiverSelectorAppInfo>;
|
let appInfo: Optional<ReceiverSelectorAppInfo>;
|
||||||
@@ -172,6 +174,8 @@
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "popup:update": {
|
case "popup:update": {
|
||||||
|
updateKnownApp();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
message.data.availableMediaTypes !== undefined &&
|
message.data.availableMediaTypes !== undefined &&
|
||||||
message.data.defaultMediaType !== undefined
|
message.data.defaultMediaType !== undefined
|
||||||
@@ -183,9 +187,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateKnownApp();
|
devices = message.data.devices;
|
||||||
|
|
||||||
devices = message.data.receiverDevices;
|
if (message.data.connectedSessionIds) {
|
||||||
|
connectedSessionIds = message.data.connectedSessionIds;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -288,30 +294,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onReceiverCast(receiverDevice: ReceiverDevice) {
|
function onReceiverCast(device: ReceiverDevice) {
|
||||||
isConnecting = true;
|
isConnecting = true;
|
||||||
|
|
||||||
port?.postMessage({
|
port?.postMessage({
|
||||||
subject: "main:receiverSelected",
|
subject: "main:receiverSelected",
|
||||||
data: {
|
data: { device, mediaType }
|
||||||
receiverDevice,
|
|
||||||
mediaType
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onReceiverStop(receiverDevice: ReceiverDevice) {
|
function onReceiverStop(device: ReceiverDevice) {
|
||||||
port?.postMessage({
|
port?.postMessage({
|
||||||
subject: "main:sendReceiverMessage",
|
subject: "main:sendReceiverMessage",
|
||||||
data: {
|
data: {
|
||||||
deviceId: receiverDevice.id,
|
deviceId: device.id,
|
||||||
message: { requestId: 0, type: "STOP" }
|
message: { requestId: 0, type: "STOP" }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
port?.postMessage({
|
port?.postMessage({
|
||||||
subject: "main:receiverStopped",
|
subject: "main:receiverStopped",
|
||||||
data: { deviceId: receiverDevice.id }
|
data: { deviceId: device.id }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -378,8 +381,10 @@
|
|||||||
{:else}
|
{:else}
|
||||||
{#each devices as device}
|
{#each devices as device}
|
||||||
<Receiver
|
<Receiver
|
||||||
|
{opts}
|
||||||
{port}
|
{port}
|
||||||
{device}
|
{device}
|
||||||
|
{connectedSessionIds}
|
||||||
{isMediaTypeAvailable}
|
{isMediaTypeAvailable}
|
||||||
isAnyMediaTypeAvailable={availableMediaTypes !==
|
isAnyMediaTypeAvailable={availableMediaTypes !==
|
||||||
ReceiverSelectorMediaType.None &&
|
ReceiverSelectorMediaType.None &&
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher, onMount } from "svelte";
|
import { createEventDispatcher, onMount } from "svelte";
|
||||||
|
|
||||||
|
import type { Options } from "../../lib/options";
|
||||||
|
|
||||||
import { ReceiverDevice, ReceiverDeviceCapabilities } from "../../types";
|
import { ReceiverDevice, ReceiverDeviceCapabilities } from "../../types";
|
||||||
import type { Port } from "../../messaging";
|
import type { Port } from "../../messaging";
|
||||||
|
|
||||||
@@ -33,8 +35,11 @@
|
|||||||
/** Whether any media types are available for this receiver. */
|
/** Whether any media types are available for this receiver. */
|
||||||
export let isAnyMediaTypeAvailable: boolean;
|
export let isAnyMediaTypeAvailable: boolean;
|
||||||
|
|
||||||
/** Receiver device to display. */
|
/** Device to display. */
|
||||||
export let device: ReceiverDevice;
|
export let device: ReceiverDevice;
|
||||||
|
export let connectedSessionIds: string[];
|
||||||
|
|
||||||
|
export let opts: Nullable<Options>;
|
||||||
|
|
||||||
/** Current receiver application (if available) */
|
/** Current receiver application (if available) */
|
||||||
$: application = device.status?.applications?.[0];
|
$: application = device.status?.applications?.[0];
|
||||||
@@ -79,8 +84,20 @@
|
|||||||
|
|
||||||
/** Whether media controls are shown. */
|
/** Whether media controls are shown. */
|
||||||
let isExpanded = false;
|
let isExpanded = false;
|
||||||
|
let isExpandedUserModified = false;
|
||||||
|
|
||||||
|
// Unexpand if media status disappears
|
||||||
$: if (!device.mediaStatus) {
|
$: if (!device.mediaStatus) {
|
||||||
isExpanded = false;
|
isExpanded = false;
|
||||||
|
} else if (
|
||||||
|
// If app is running
|
||||||
|
application?.appId &&
|
||||||
|
// And user hasn't manually changed the expanded state
|
||||||
|
!isExpandedUserModified &&
|
||||||
|
// And auto-expansion is enabled
|
||||||
|
opts?.receiverSelectorExpandActive
|
||||||
|
) {
|
||||||
|
isExpanded = connectedSessionIds.includes(application?.transportId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether a session request is in progress for this receiver.. */
|
/** Whether a session request is in progress for this receiver.. */
|
||||||
@@ -429,6 +446,7 @@
|
|||||||
disabled={!mediaStatus}
|
disabled={!mediaStatus}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
isExpanded = !isExpanded;
|
isExpanded = !isExpanded;
|
||||||
|
isExpandedUserModified = true;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user