mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-08 08:39:59 +00:00
Misc popup refactoring/documentation
This commit is contained in:
@@ -5,7 +5,6 @@ import messaging, { Port, Message } from "../../messaging";
|
|||||||
import options from "../../lib/options";
|
import options from "../../lib/options";
|
||||||
|
|
||||||
import { TypedEventTarget } from "../../lib/TypedEventTarget";
|
import { TypedEventTarget } from "../../lib/TypedEventTarget";
|
||||||
import { getWindowCenteredProps, WindowCenteredProps } from "../../lib/utils";
|
|
||||||
import { ReceiverDevice } from "../../types";
|
import { ReceiverDevice } from "../../types";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -29,6 +28,10 @@ export interface PageInfo {
|
|||||||
frameId: number;
|
frameId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the receiver selector popup window and communication with the
|
||||||
|
* extension page hosted within.
|
||||||
|
*/
|
||||||
export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorEvents> {
|
export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorEvents> {
|
||||||
private windowId?: number;
|
private windowId?: number;
|
||||||
|
|
||||||
@@ -49,7 +52,6 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
// Bind methods to pass to addListener
|
|
||||||
this.onConnect = this.onConnect.bind(this);
|
this.onConnect = this.onConnect.bind(this);
|
||||||
this.onPopupMessage = this.onPopupMessage.bind(this);
|
this.onPopupMessage = this.onPopupMessage.bind(this);
|
||||||
this.onWindowsRemoved = this.onWindowsRemoved.bind(this);
|
this.onWindowsRemoved = this.onWindowsRemoved.bind(this);
|
||||||
@@ -68,13 +70,16 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
return this.#isOpen;
|
return this.#isOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and opens a receiver selector window.
|
||||||
|
*/
|
||||||
public async open(
|
public async open(
|
||||||
receiverDevices: ReceiverDevice[],
|
receiverDevices: ReceiverDevice[],
|
||||||
defaultMediaType: ReceiverSelectorMediaType,
|
defaultMediaType: ReceiverSelectorMediaType,
|
||||||
availableMediaTypes: ReceiverSelectorMediaType,
|
availableMediaTypes: ReceiverSelectorMediaType,
|
||||||
appId?: string,
|
appId?: string,
|
||||||
pageInfo?: PageInfo
|
pageInfo?: PageInfo
|
||||||
): Promise<void> {
|
) {
|
||||||
this.appId = appId;
|
this.appId = appId;
|
||||||
this.pageInfo = pageInfo;
|
this.pageInfo = pageInfo;
|
||||||
|
|
||||||
@@ -87,54 +92,59 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
this.defaultMediaType = defaultMediaType;
|
this.defaultMediaType = defaultMediaType;
|
||||||
this.availableMediaTypes = availableMediaTypes;
|
this.availableMediaTypes = availableMediaTypes;
|
||||||
|
|
||||||
let centeredProps: WindowCenteredProps = {
|
const popupSizePosition = {
|
||||||
left: 100,
|
|
||||||
top: 100,
|
|
||||||
width: 350,
|
width: 350,
|
||||||
height: 200
|
height: 200,
|
||||||
|
left: 100,
|
||||||
|
top: 100
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
/**
|
||||||
// Calculate centered size/position based on current window
|
* Get current browser window and calculate relative centered
|
||||||
centeredProps = getWindowCenteredProps(
|
* left/top positions for the popup.
|
||||||
await browser.windows.getCurrent(),
|
*/
|
||||||
centeredProps.width,
|
const refWin = await browser.windows.getCurrent();
|
||||||
centeredProps.height
|
if (refWin.width && refWin.height && refWin.left && refWin.top) {
|
||||||
|
const centerX = refWin.left + refWin.width / 2;
|
||||||
|
const centerY = refWin.top + refWin.height / 3;
|
||||||
|
|
||||||
|
popupSizePosition.left = Math.floor(
|
||||||
|
centerX - popupSizePosition.width / 2
|
||||||
);
|
);
|
||||||
} catch {
|
popupSizePosition.top = Math.floor(
|
||||||
// Shouldn't ever hit this, but defaults are provided in case
|
centerY - popupSizePosition.height / 2
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
logger.log("Reference window missing positional properties.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create popup window
|
||||||
const popup = await browser.windows.create({
|
const popup = await browser.windows.create({
|
||||||
url: POPUP_URL,
|
url: POPUP_URL,
|
||||||
type: "popup",
|
type: "popup",
|
||||||
...centeredProps
|
...popupSizePosition
|
||||||
});
|
});
|
||||||
|
|
||||||
if (popup?.id === undefined) {
|
if (popup?.id === undefined) {
|
||||||
throw logger.error("Failed to create receiver selector popup.");
|
throw logger.error("Failed to create receiver selector popup.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Size/position not set correctly on creation (bug 1396881)
|
||||||
|
await browser.windows.update(popup.id, {
|
||||||
|
...popupSizePosition
|
||||||
|
});
|
||||||
|
|
||||||
this.#isOpen = true;
|
this.#isOpen = true;
|
||||||
this.windowId = popup.id;
|
this.windowId = popup.id;
|
||||||
|
|
||||||
// Size/position not set correctly on creation (bug?)
|
// Add focus listener
|
||||||
await browser.windows.update(this.windowId, {
|
if (await options.get("receiverSelectorCloseIfFocusLost")) {
|
||||||
...centeredProps
|
|
||||||
});
|
|
||||||
|
|
||||||
const closeIfFocusLost = await options.get(
|
|
||||||
"receiverSelectorCloseIfFocusLost"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (closeIfFocusLost) {
|
|
||||||
// Add focus listener
|
|
||||||
browser.windows.onFocusChanged.addListener(
|
browser.windows.onFocusChanged.addListener(
|
||||||
this.onWindowsFocusChanged
|
this.onWindowsFocusChanged
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Updates receiver devices displayed in the receiver selector. */
|
||||||
public update(receiverDevices: ReceiverDevice[]) {
|
public update(receiverDevices: ReceiverDevice[]) {
|
||||||
this.receiverDevices = receiverDevices;
|
this.receiverDevices = receiverDevices;
|
||||||
this.messagePort?.postMessage({
|
this.messagePort?.postMessage({
|
||||||
@@ -145,7 +155,8 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async close(): Promise<void> {
|
/** Closes the receiver selector (if open). */
|
||||||
|
public async close() {
|
||||||
if (this.windowId) {
|
if (this.windowId) {
|
||||||
await browser.windows.remove(this.windowId);
|
await browser.windows.remove(this.windowId);
|
||||||
}
|
}
|
||||||
@@ -158,16 +169,19 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles incoming port connection from the extension page and
|
||||||
|
* sends init data.
|
||||||
|
*/
|
||||||
private onConnect(port: Port) {
|
private onConnect(port: Port) {
|
||||||
|
// Keep history state clean
|
||||||
browser.history.deleteUrl({ url: POPUP_URL });
|
browser.history.deleteUrl({ url: POPUP_URL });
|
||||||
|
|
||||||
if (port.name !== "popup") {
|
if (port.name !== "popup") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.messagePort) {
|
this.messagePort?.disconnect();
|
||||||
this.messagePort.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.messagePort = port;
|
this.messagePort = port;
|
||||||
this.messagePort.onMessage.addListener(this.onPopupMessage);
|
this.messagePort.onMessage.addListener(this.onPopupMessage);
|
||||||
@@ -180,7 +194,8 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
this.defaultMediaType === undefined ||
|
this.defaultMediaType === undefined ||
|
||||||
this.availableMediaTypes === undefined
|
this.availableMediaTypes === undefined
|
||||||
) {
|
) {
|
||||||
throw logger.error("Popup receiver data not found.");
|
logger.error("Popup receiver data not found.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.messagePort.postMessage({
|
this.messagePort.postMessage({
|
||||||
@@ -196,13 +211,9 @@ export default class ReceiverSelector extends TypedEventTarget<ReceiverSelectorE
|
|||||||
availableMediaTypes: this.availableMediaTypes
|
availableMediaTypes: this.availableMediaTypes
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
messaging.onConnect.removeListener(this.onConnect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Handles messages from the popup extension page. */
|
||||||
* Handles popup messages.
|
|
||||||
*/
|
|
||||||
private onPopupMessage(message: Message) {
|
private onPopupMessage(message: Message) {
|
||||||
switch (message.subject) {
|
switch (message.subject) {
|
||||||
case "receiverSelector:selected": {
|
case "receiverSelector:selected": {
|
||||||
|
|||||||
@@ -79,38 +79,6 @@ export function getMediaTypesForPageUrl(
|
|||||||
return availableMediaTypes;
|
return availableMediaTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WindowCenteredProps {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
left: number;
|
|
||||||
top: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getWindowCenteredProps(
|
|
||||||
refWin: browser.windows.Window,
|
|
||||||
width: number,
|
|
||||||
height: number
|
|
||||||
): WindowCenteredProps {
|
|
||||||
if (
|
|
||||||
refWin.left === undefined ||
|
|
||||||
refWin.width === undefined ||
|
|
||||||
refWin.top === undefined ||
|
|
||||||
refWin.height === undefined
|
|
||||||
) {
|
|
||||||
throw logger.error("refWin missing positional attributes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const centerX = refWin.left + refWin.width / 2;
|
|
||||||
const centerY = refWin.top + refWin.height / 3;
|
|
||||||
|
|
||||||
return {
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
left: Math.floor(centerX - width / 2),
|
|
||||||
top: Math.floor(centerY - height / 2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loadScript(
|
export function loadScript(
|
||||||
scriptUrl: string,
|
scriptUrl: string,
|
||||||
doc: Document = document
|
doc: Document = document
|
||||||
|
|||||||
Reference in New Issue
Block a user