mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-13 11:00:01 +00:00
Add initial ReceiverSelectorManager implementations
This commit is contained in:
22
ext/src/receiverSelectorManager/ReceiverSelectorManager.ts
Normal file
22
ext/src/receiverSelectorManager/ReceiverSelectorManager.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
import { Receiver } from "../types"
|
||||||
|
|
||||||
|
|
||||||
|
export type ReceiverSelectorSelectedEvent = CustomEvent<Receiver>;
|
||||||
|
export type ReceiverSelectorErrorEvent = CustomEvent;
|
||||||
|
export type ReceiverSelectorCancelledEvent = CustomEvent;
|
||||||
|
|
||||||
|
export enum ReceiverSelectorCastType {
|
||||||
|
App
|
||||||
|
, Tab
|
||||||
|
, Screen
|
||||||
|
}
|
||||||
|
|
||||||
|
export default interface ReceiverSelectorManager extends EventTarget {
|
||||||
|
open (
|
||||||
|
receivers: Receiver[]
|
||||||
|
, defaultCastType: ReceiverSelectorCastType): void;
|
||||||
|
|
||||||
|
close (): void;
|
||||||
|
}
|
||||||
7
ext/src/receiverSelectorManager/index.ts
Normal file
7
ext/src/receiverSelectorManager/index.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
export { default as NativeMacReceiverSelectorManager }
|
||||||
|
from "./selectorManagers/NativeMacReceiverSelectorManager";
|
||||||
|
|
||||||
|
export { default as PopupReceiverSelectorManager }
|
||||||
|
from "./selectorManagers/PopupReceiverSelectorManager";
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
import ReceiverSelectorManager, {
|
||||||
|
ReceiverSelectorCastType } from "../ReceiverSelectorManager";
|
||||||
|
|
||||||
|
import { Receiver, Message } from "../../types";
|
||||||
|
|
||||||
|
|
||||||
|
class NativeMacReceiverSelectorManager
|
||||||
|
extends EventTarget
|
||||||
|
implements ReceiverSelectorManager {
|
||||||
|
|
||||||
|
public async open (
|
||||||
|
receivers: Receiver[]
|
||||||
|
, defaultCastType: ReceiverSelectorCastType): Promise<void> {
|
||||||
|
console.info("STUB :: NativeMacReceiverSelectorManager.open");
|
||||||
|
}
|
||||||
|
|
||||||
|
public close (): void {
|
||||||
|
console.info("STUB :: NativeMacReceiverSelectorManager.close");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Singleton instance
|
||||||
|
export default new NativeMacReceiverSelectorManager();
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
import ReceiverSelectorManager, {
|
||||||
|
ReceiverSelectorCastType } from "../ReceiverSelectorManager";
|
||||||
|
|
||||||
|
import { Receiver, Message } from "../../types";
|
||||||
|
import { getWindowCenteredProps } from "../../lib/utils";
|
||||||
|
|
||||||
|
|
||||||
|
class PopupReceiverSelectorManager
|
||||||
|
extends EventTarget
|
||||||
|
implements ReceiverSelectorManager {
|
||||||
|
|
||||||
|
private windowId: number;
|
||||||
|
private openerWindowId: number;
|
||||||
|
private messagePort: browser.runtime.Port;
|
||||||
|
|
||||||
|
private receivers: Receiver[];
|
||||||
|
private defaultCastType: ReceiverSelectorCastType;
|
||||||
|
|
||||||
|
private wasReceiverSelected: boolean = false;
|
||||||
|
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// Bind methods to pass to addListener
|
||||||
|
this.onPopupMessage = this.onPopupMessage.bind(this);
|
||||||
|
this.onWindowsRemoved = this.onWindowsRemoved.bind(this);
|
||||||
|
this.onWindowsFocusChanged = this.onWindowsFocusChanged.bind(this);
|
||||||
|
|
||||||
|
browser.windows.onRemoved.addListener(this.onWindowsRemoved);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle incoming message channel connection from popup
|
||||||
|
* window script.
|
||||||
|
*/
|
||||||
|
browser.runtime.onConnect.addListener(port => {
|
||||||
|
if (port.name !== "popup") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disconnect existing port
|
||||||
|
if (this.messagePort) {
|
||||||
|
this.messagePort.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.messagePort = port;
|
||||||
|
this.messagePort.onMessage.addListener(this.onPopupMessage);
|
||||||
|
|
||||||
|
// TODO: Send initial data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async open (
|
||||||
|
receivers: Receiver[]
|
||||||
|
, defaultCastType: ReceiverSelectorCastType): Promise<void> {
|
||||||
|
|
||||||
|
// If popup already exists, close it
|
||||||
|
if (this.windowId) {
|
||||||
|
await browser.windows.remove(this.windowId);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.receivers = receivers;
|
||||||
|
this.defaultCastType = defaultCastType;
|
||||||
|
|
||||||
|
// Current window to base centered position on
|
||||||
|
const openerWindow = await browser.windows.getCurrent();
|
||||||
|
const centeredProps = getWindowCenteredProps(openerWindow, 350, 200);
|
||||||
|
|
||||||
|
const popup = await browser.windows.create({
|
||||||
|
url: "ui/popup/index.html"
|
||||||
|
, type: "popup"
|
||||||
|
, ...centeredProps
|
||||||
|
});
|
||||||
|
|
||||||
|
this.windowId = popup.id;
|
||||||
|
this.openerWindowId = openerWindow.id;
|
||||||
|
|
||||||
|
// Size/position not set correctly on creation (bug?)
|
||||||
|
await browser.windows.update(this.windowId, {
|
||||||
|
...centeredProps
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add focus listener
|
||||||
|
browser.windows.onFocusChanged.addListener(
|
||||||
|
this.onWindowsFocusChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
public close (): void {
|
||||||
|
browser.windows.remove(this.windowId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles popup messages.
|
||||||
|
*/
|
||||||
|
private onPopupMessage (message: Message) {
|
||||||
|
switch (message.subject) {
|
||||||
|
case "selected": {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles cancellation state where the popup window is closed
|
||||||
|
* before a receiver is selected.
|
||||||
|
*/
|
||||||
|
private onWindowsRemoved (windowId: number) {
|
||||||
|
// Only care about popup window
|
||||||
|
if (windowId !== this.windowId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.windows.onFocusChanged.removeListener(
|
||||||
|
this.onWindowsFocusChanged);
|
||||||
|
|
||||||
|
if (!this.wasReceiverSelected) {
|
||||||
|
this.dispatchEvent(new CustomEvent("cancelled"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
this.windowId = null;
|
||||||
|
this.openerWindowId = null;
|
||||||
|
this.messagePort = null;
|
||||||
|
this.receivers = null;
|
||||||
|
this.defaultCastType = null;
|
||||||
|
this.wasReceiverSelected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes popup window if another browser window is brought
|
||||||
|
* into focus. Doesn't apply if no window is focused
|
||||||
|
* `WINDOW_ID_NONE` or if the popup window is re-focused.
|
||||||
|
*/
|
||||||
|
private onWindowsFocusChanged (windowId: number) {
|
||||||
|
if (windowId !== browser.windows.WINDOW_ID_NONE
|
||||||
|
&& windowId !== this.windowId) {
|
||||||
|
|
||||||
|
// Only run once
|
||||||
|
browser.windows.onFocusChanged.removeListener(
|
||||||
|
this.onWindowsFocusChanged);
|
||||||
|
|
||||||
|
browser.windows.remove(this.windowId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Singleton instance
|
||||||
|
export default new PopupReceiverSelectorManager();
|
||||||
@@ -7,10 +7,11 @@ export interface Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Receiver {
|
export interface Receiver {
|
||||||
friendlyName: string;
|
|
||||||
address: string;
|
address: string;
|
||||||
port: number;
|
|
||||||
currentApp: string;
|
currentApp: string;
|
||||||
|
friendlyName: string;
|
||||||
|
id: string;
|
||||||
|
port: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DownloadDelta {
|
export interface DownloadDelta {
|
||||||
|
|||||||
Reference in New Issue
Block a user