mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-08 08:39:59 +00:00
Set browser action details to match cast session states
This commit is contained in:
@@ -8,6 +8,23 @@
|
|||||||
"description": "Description of the extension shown in the add-ons manager."
|
"description": "Description of the extension shown in the add-ons manager."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"actionTitleDefault": {
|
||||||
|
"message": "fx_cast: Ready to cast",
|
||||||
|
"description": "Title for toolbar button in default state."
|
||||||
|
},
|
||||||
|
"actionTitleDisabled": {
|
||||||
|
"message": "fx_cast: Unable to cast",
|
||||||
|
"description": "Title for toolbar button in disabled state."
|
||||||
|
},
|
||||||
|
"actionTitleConnecting": {
|
||||||
|
"message": "fx_cast: Connecting",
|
||||||
|
"description": "Title for toolbar button whilst connecting."
|
||||||
|
},
|
||||||
|
"actionTitleConnected": {
|
||||||
|
"message": "fx_cast: Connected",
|
||||||
|
"description": "Title for toolbar button whilst connected."
|
||||||
|
},
|
||||||
|
|
||||||
"popupBridgeErrorBanner": {
|
"popupBridgeErrorBanner": {
|
||||||
"message": "There is a problem with the bridge!",
|
"message": "There is a problem with the bridge!",
|
||||||
"description": "Bridge error banner message."
|
"description": "Bridge error banner message."
|
||||||
|
|||||||
75
ext/src/background/action.ts
Normal file
75
ext/src/background/action.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import logger from "../lib/logger";
|
||||||
|
import castManager from "./castManager";
|
||||||
|
|
||||||
|
const _ = browser.i18n.getMessage;
|
||||||
|
|
||||||
|
const ACTION_ICON_DEFAULT_DARK = "icons/cast-default-dark.svg";
|
||||||
|
const ACTION_ICON_DEFAULT_LIGHT = "icons/cast-default-light.svg";
|
||||||
|
const ACTION_ICON_CONNECTING_DARK = "icons/cast-connecting-dark.svg";
|
||||||
|
const ACTION_ICON_CONNECTING_LIGHT = "icons/cast-connecting-light.svg";
|
||||||
|
const ACTION_ICON_CONNECTED = "icons/cast-connected.svg";
|
||||||
|
const ACTION_ICON_DISABLED_DARK = "icons/cast-disabled-dark.svg";
|
||||||
|
const ACTION_ICON_DISABLED_LIGHT = "icons/cast-disabled-light.svg";
|
||||||
|
|
||||||
|
const isDarkTheme = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
|
|
||||||
|
export enum ActionState {
|
||||||
|
Default,
|
||||||
|
Connecting,
|
||||||
|
Connected,
|
||||||
|
Disabled
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Updates action details depending on given state. */
|
||||||
|
export function updateActionState(state: ActionState, tabId?: number) {
|
||||||
|
let title: string;
|
||||||
|
let path: string;
|
||||||
|
switch (state) {
|
||||||
|
case ActionState.Default:
|
||||||
|
title = _("actionTitleDefault");
|
||||||
|
path = isDarkTheme
|
||||||
|
? ACTION_ICON_DEFAULT_LIGHT
|
||||||
|
: ACTION_ICON_DEFAULT_DARK;
|
||||||
|
break;
|
||||||
|
case ActionState.Connecting:
|
||||||
|
title = _("actionTitleConnecting");
|
||||||
|
path = isDarkTheme
|
||||||
|
? ACTION_ICON_CONNECTING_LIGHT
|
||||||
|
: ACTION_ICON_CONNECTING_DARK;
|
||||||
|
break;
|
||||||
|
case ActionState.Connected:
|
||||||
|
title = _("actionTitleConnected");
|
||||||
|
path = ACTION_ICON_CONNECTED;
|
||||||
|
break;
|
||||||
|
case ActionState.Disabled:
|
||||||
|
title = _("actionTitleDisabled");
|
||||||
|
path = isDarkTheme
|
||||||
|
? ACTION_ICON_DISABLED_LIGHT
|
||||||
|
: ACTION_ICON_DISABLED_DARK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state === ActionState.Disabled) {
|
||||||
|
browser.browserAction.disable(tabId);
|
||||||
|
} else {
|
||||||
|
browser.browserAction.enable(tabId);
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.browserAction.setTitle({ tabId, title });
|
||||||
|
browser.browserAction.setIcon({ tabId, path });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initAction() {
|
||||||
|
logger.info("init (action)");
|
||||||
|
|
||||||
|
updateActionState(ActionState.Default);
|
||||||
|
|
||||||
|
browser.browserAction.onClicked.addListener(async tab => {
|
||||||
|
if (tab.id === undefined) {
|
||||||
|
logger.error("Tab ID not found in browser action handler.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
castManager.triggerCast(tab.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import messaging from "../messaging";
|
|||||||
import castManager from "./castManager";
|
import castManager from "./castManager";
|
||||||
import deviceManager from "./deviceManager";
|
import deviceManager from "./deviceManager";
|
||||||
|
|
||||||
|
import { initAction } from "./action";
|
||||||
import { initMenus } from "./menus";
|
import { initMenus } from "./menus";
|
||||||
import { initWhitelist } from "./whitelist";
|
import { initWhitelist } from "./whitelist";
|
||||||
|
|
||||||
@@ -129,6 +130,7 @@ async function init() {
|
|||||||
await deviceManager.init();
|
await deviceManager.init();
|
||||||
await castManager.init();
|
await castManager.init();
|
||||||
|
|
||||||
|
await initAction();
|
||||||
await initMenus();
|
await initMenus();
|
||||||
await initWhitelist();
|
await initWhitelist();
|
||||||
|
|
||||||
@@ -139,15 +141,6 @@ async function init() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
browser.browserAction.onClicked.addListener(async tab => {
|
|
||||||
if (tab.id === undefined) {
|
|
||||||
logger.error("Tab ID not found in browser action handler.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
castManager.triggerCast(tab.id);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheBaseConfig();
|
cacheBaseConfig();
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import ReceiverSelector, {
|
|||||||
} from "./ReceiverSelector";
|
} from "./ReceiverSelector";
|
||||||
|
|
||||||
import deviceManager from "./deviceManager";
|
import deviceManager from "./deviceManager";
|
||||||
|
import { ActionState, updateActionState } from "./action";
|
||||||
|
|
||||||
type AnyPort = Port | TypedMessagePort<Message>;
|
type AnyPort = Port | TypedMessagePort<Message>;
|
||||||
|
|
||||||
@@ -85,6 +86,13 @@ async function createCastSession(opts: {
|
|||||||
destroyCastInstance(opts.instance)
|
destroyCastInstance(opts.instance)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (opts.instance.contentContext?.tabId) {
|
||||||
|
updateActionState(
|
||||||
|
ActionState.Connecting,
|
||||||
|
opts.instance.contentContext?.tabId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,6 +169,10 @@ function destroyCastInstance(instance: CastInstance) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instance.contentContext?.tabId) {
|
||||||
|
updateActionState(ActionState.Default, instance.contentContext?.tabId);
|
||||||
|
}
|
||||||
|
|
||||||
activeInstances.delete(instance);
|
activeInstances.delete(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +239,13 @@ const castManager = new (class {
|
|||||||
});
|
});
|
||||||
|
|
||||||
delete instance.session;
|
delete instance.session;
|
||||||
|
|
||||||
|
if (instance.contentContext?.tabId) {
|
||||||
|
updateActionState(
|
||||||
|
ActionState.Default,
|
||||||
|
instance.contentContext?.tabId
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,6 +426,13 @@ async function handleBridgeMessage(instance: CastInstance, message: Message) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (instance.contentContext?.tabId) {
|
||||||
|
updateActionState(
|
||||||
|
ActionState.Connected,
|
||||||
|
instance.contentContext?.tabId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,6 +555,13 @@ async function handleContentMessage(instance: CastInstance, message: Message) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (instance.contentContext?.tabId) {
|
||||||
|
updateActionState(
|
||||||
|
ActionState.Connected,
|
||||||
|
instance.contentContext?.tabId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
break sessionLoop;
|
break sessionLoop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import type {
|
|||||||
} from "../cast/sdk/types";
|
} from "../cast/sdk/types";
|
||||||
import { PlayerState } from "../cast/sdk/media/enums";
|
import { PlayerState } from "../cast/sdk/media/enums";
|
||||||
|
|
||||||
|
import { ActionState, updateActionState } from "./action";
|
||||||
|
|
||||||
interface EventMap {
|
interface EventMap {
|
||||||
deviceUp: { deviceInfo: ReceiverDevice };
|
deviceUp: { deviceInfo: ReceiverDevice };
|
||||||
deviceDown: { deviceId: string };
|
deviceDown: { deviceId: string };
|
||||||
@@ -45,6 +47,8 @@ export default new (class extends TypedEventTarget<EventMap> {
|
|||||||
async refresh() {
|
async refresh() {
|
||||||
this.bridgePort?.disconnect();
|
this.bridgePort?.disconnect();
|
||||||
|
|
||||||
|
updateActionState(ActionState.Disabled);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.bridgeInfo = await bridge.getInfo();
|
this.bridgeInfo = await bridge.getInfo();
|
||||||
// eslint-disable-next-line no-empty
|
// eslint-disable-next-line no-empty
|
||||||
@@ -65,6 +69,14 @@ export default new (class extends TypedEventTarget<EventMap> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateAction() {
|
||||||
|
if (this.receiverDevices.size > 0) {
|
||||||
|
updateActionState(ActionState.Default);
|
||||||
|
} else {
|
||||||
|
updateActionState(ActionState.Disabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getBridgeInfo() {
|
getBridgeInfo() {
|
||||||
return this.bridgeInfo;
|
return this.bridgeInfo;
|
||||||
}
|
}
|
||||||
@@ -142,6 +154,8 @@ export default new (class extends TypedEventTarget<EventMap> {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.updateAction();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,6 +171,8 @@ export default new (class extends TypedEventTarget<EventMap> {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.updateAction();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user